home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / jove / part04 < prev    next >
Encoding:
Internet Message Format  |  1987-02-02  |  58.4 KB

  1. Subject:  v08i023:  The JOVE text editor, Part04/13
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: seismo!rochester!jpayne (Jonathan Payne)
  6. Mod.sources: Volume 8, Issue 23
  7. Archive-name: jove/Part04
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If all goes well, you will see the message "End of archive 4 (of 13)."
  13. # Contents:  io.c iproc-pipes.c iproc-ptys.c iproc.c keymaps.txt rec.c
  14. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  15. echo shar: extracting "'io.c'" '(20767 characters)'
  16. if test -f 'io.c' ; then 
  17.   echo shar: will not over-write existing file "'io.c'"
  18. else
  19. sed 's/^X//' >io.c <<'@//E*O*F io.c//'
  20. X/************************************************************************
  21. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  22. X * provided to you without charge, and with no warranty.  You may give  *
  23. X * away copies of JOVE, including sources, provided that this notice is *
  24. X * included in all the files.                                           *
  25. X ************************************************************************/
  26. X
  27. X#include "jove.h"
  28. X#include "io.h"
  29. X#include "termcap.h"
  30. X
  31. X#ifdef IPROCS
  32. X#   include <signal.h>
  33. X#endif
  34. X
  35. X#include <sys/stat.h>
  36. X#include <sys/file.h>
  37. X#include <errno.h>
  38. X
  39. X#ifndef W_OK
  40. X#   define W_OK    2
  41. X#   define F_OK    0
  42. X#endif
  43. X
  44. Xlong    io_chars;        /* number of chars in this open_file */
  45. Xint    io_lines;        /* number of lines in this open_file */
  46. Xprivate int    tellall;    /* display file io info? */
  47. X
  48. X#ifdef VMUNIX
  49. Xchar    iobuff[LBSIZE],
  50. X    genbuf[LBSIZE],
  51. X    linebuf[LBSIZE];
  52. X#else
  53. Xchar    *iobuff,
  54. X    *genbuf,
  55. X    *linebuf;
  56. X#endif
  57. X
  58. X#ifdef BACKUPFILES
  59. Xint    BkupOnWrite = 0;
  60. X#endif
  61. X
  62. Xclose_file(fp)
  63. XFile    *fp;
  64. X{
  65. X    if (fp) {
  66. X        f_close(fp);
  67. X        if (tellall != QUIET)
  68. X            add_mess(" %d lines, %D characters.",
  69. X                 io_lines,
  70. X                 io_chars);
  71. X    }
  72. X}
  73. X
  74. X/* Write the region from line1/char1 to line2/char2 to FP.  This
  75. X   never CLOSES the file since we don't know if we want to. */
  76. X
  77. Xint    EndWNewline = 1;
  78. X
  79. Xputreg(fp, line1, char1, line2, char2, makesure)
  80. Xregister File    *fp;
  81. XLine    *line1,
  82. X    *line2;
  83. X{
  84. X    register int    c;
  85. X    register char    *lp;
  86. X
  87. X    if (makesure)
  88. X        (void) fixorder(&line1, &char1, &line2, &char2);
  89. X    while (line1 != line2->l_next) {
  90. X        lp = lcontents(line1) + char1;
  91. X        if (line1 == line2) {
  92. X            fputnchar(lp, (char2 - char1), fp);
  93. X            io_chars += (char2 - char1);
  94. X        } else while (c = *lp++) {
  95. X            putc(c, fp);
  96. X            io_chars++;
  97. X        }
  98. X        if (line1 != line2) {
  99. X            io_lines++;
  100. X            io_chars++;
  101. X            putc('\n', fp);
  102. X        }
  103. X        line1 = line1->l_next;
  104. X        char1 = 0;
  105. X    }
  106. X    flush(fp);
  107. X}
  108. X
  109. Xread_file(file, is_insert)
  110. Xchar    *file;
  111. X{
  112. X    Bufpos    save;
  113. X    File    *fp;
  114. X
  115. X    if (!is_insert) {
  116. X        curbuf->b_ntbf = 0;
  117. X        set_ino(curbuf);
  118. X    }
  119. X    fp = open_file(file, iobuff, F_READ, !COMPLAIN, !QUIET);
  120. X    if (fp == NIL) {
  121. X        if (!is_insert && errno == ENOENT)
  122. X            s_mess("(new file)");
  123. X        else
  124. X            s_mess(IOerr("open", file));
  125. X        return;
  126. X    }
  127. X    DOTsave(&save);
  128. X    dofread(fp);
  129. X    SetDot(&save);
  130. X    if (is_insert && io_chars > 0)
  131. X        modify();
  132. X    getDOT();
  133. X    close_file(fp);
  134. X}
  135. X
  136. Xdofread(fp)
  137. Xregister File    *fp;
  138. X{
  139. X    char    end[LBSIZE];
  140. X    int    xeof = 0;
  141. X    Line    *savel = curline;
  142. X    int    savec = curchar;
  143. X    disk_line    f_getputl() ;
  144. X
  145. X    strcpy(end, linebuf + curchar);
  146. X    xeof = f_gets(fp, linebuf + curchar, LBSIZE - curchar);
  147. X    SavLine(curline, linebuf);
  148. X    if (!xeof) do {
  149. X        curline = listput(curbuf, curline);
  150. X        xeof = f_getputl(curline, fp);
  151. X    } while (!xeof);
  152. X    getDOT();
  153. X    linecopy(linebuf, (curchar = strlen(linebuf)), end);
  154. X    SavLine(curline, linebuf);
  155. X    IFixMarks(savel, savec, curline, curchar);
  156. X}
  157. X
  158. XSaveFile()
  159. X{
  160. X    if (IsModified(curbuf)) {
  161. X        if (curbuf->b_fname == 0)
  162. X            WriteFile();
  163. X        else {
  164. X            filemunge(curbuf->b_fname);
  165. X            chk_mtime(curbuf, curbuf->b_fname, "save");
  166. X            file_write(curbuf->b_fname, 0);
  167. X            unmodify();
  168. X        }
  169. X    } else
  170. X        message("No changes need to be written.");
  171. X}
  172. X
  173. Xchar    *HomeDir;    /* home directory */
  174. Xint    HomeLen = -1;    /* length of home directory string */
  175. X
  176. X#ifndef CHDIR
  177. X
  178. Xchar *
  179. Xpr_name(fname)
  180. Xchar    *fname;
  181. X{
  182. X    if (fname == 0)
  183. X        return 0;
  184. X
  185. X    if (strncmp(fname, HomeDir, HomeLen) == 0) {
  186. X        static char    name_buf[100];
  187. X
  188. X        sprintf(name_buf, "~%s", fname + HomeLen);
  189. X        return name_buf;
  190. X    }
  191. X
  192. X    return fname;
  193. X}
  194. X
  195. X#else
  196. X
  197. X#define NDIRS    5
  198. X
  199. Xprivate char    *DirStack[NDIRS] = {0};
  200. Xprivate int    DirSP = 0;    /* Directory stack pointer */
  201. X#define PWD    (DirStack[DirSP])
  202. X
  203. Xchar *
  204. Xpwd()
  205. X{
  206. X    return PWD;
  207. X}
  208. X
  209. Xchar *
  210. Xpr_name(fname)
  211. Xchar    *fname;
  212. X{
  213. X    int    n;
  214. X
  215. X    if (fname == 0)
  216. X        return 0;
  217. X    n = numcomp(fname, PWD);
  218. X
  219. X    if ((PWD[n] == 0) &&    /* Matched to end of PWD */
  220. X        (fname[n] == '/'))
  221. X        return fname + n + 1;
  222. X
  223. X    if (strcmp(HomeDir, "/") != 0 && strncmp(fname, HomeDir, HomeLen) == 0) {
  224. X        static char    name_buf[100];
  225. X
  226. X        sprintf(name_buf, "~%s", fname + HomeLen);
  227. X        return name_buf;
  228. X    }
  229. X
  230. X    return fname;    /* return entire path name */
  231. X}
  232. X
  233. XChdir()
  234. X{
  235. X    char    dirbuf[FILESIZE];
  236. X
  237. X    (void) ask_file((char *) 0, PWD, dirbuf);
  238. X    if (chdir(dirbuf) == -1) {
  239. X        s_mess("cd: cannot change into %s.", dirbuf);
  240. X        return;
  241. X    }
  242. X    UpdModLine++;
  243. X    setCWD(dirbuf);
  244. X}
  245. X
  246. X#ifndef JOB_CONTROL
  247. Xchar *
  248. Xgetwd()
  249. X{
  250. X    Buffer    *old = curbuf;
  251. X    char    *ret_val;
  252. X
  253. X    SetBuf(do_select((Window *) 0, "pwd-output"));
  254. X    curbuf->b_type = B_PROCESS;
  255. X    (void) UnixToBuf("pwd-output", NO, 0, YES, "/bin/pwd", (char *) 0);
  256. X    ToFirst();
  257. X    ret_val = sprint(linebuf);
  258. X    SetBuf(old);
  259. X    return ret_val;
  260. X}
  261. X#endif
  262. X
  263. XsetCWD(d)
  264. Xchar    *d;
  265. X{
  266. X    if (PWD == 0)
  267. X        PWD = malloc((unsigned) strlen(d) + 1);
  268. X    else {
  269. X        extern char    *ralloc();
  270. X
  271. X        PWD = ralloc(PWD, strlen(d) + 1);
  272. X    }
  273. X    strcpy(PWD, d);
  274. X}
  275. X
  276. XgetCWD()
  277. X{
  278. X    char    *cwd = getenv("CWD");
  279. X#ifdef JOB_CONTROL
  280. X    extern char    *getwd();
  281. X    char    pathname[FILESIZE];
  282. X#endif
  283. X
  284. X    if (cwd == 0)
  285. X#ifdef JOB_CONTROL
  286. X        cwd = getwd(pathname);
  287. X#else
  288. X        cwd = getwd();
  289. X#endif
  290. X
  291. X    setCWD(cwd);
  292. X}    
  293. X
  294. XprDIRS()
  295. X{
  296. X    register int    i;
  297. X
  298. X    s_mess(": %f ");
  299. X    for (i = DirSP; i >= 0; i--)
  300. X        add_mess("%s ", pr_name(DirStack[i]));
  301. X}
  302. X
  303. XprCWD()
  304. X{
  305. X    s_mess(": %f => \"%s\"", PWD);
  306. X}
  307. X
  308. XPushd()
  309. X{
  310. X    char    *newdir,
  311. X        dirbuf[FILESIZE];
  312. X
  313. X    newdir = ask_file((char *) 0, NullStr, dirbuf);
  314. X    UpdModLine++;
  315. X    if (*newdir == 0) {    /* Wants to swap top two entries */
  316. X        char    *old_top;
  317. X
  318. X        if (DirSP == 0)
  319. X            complain("pushd: no other directory.");
  320. X        old_top = PWD;
  321. X        DirStack[DirSP] = DirStack[DirSP - 1];
  322. X        DirStack[DirSP - 1] = old_top;
  323. X        (void) chdir(PWD);
  324. X    } else {
  325. X        if (chdir(dirbuf) == -1) {
  326. X            s_mess("pushd: cannot change into %s.", dirbuf);
  327. X            return;
  328. X        }
  329. X
  330. X        if (DirSP + 1 >= NDIRS)
  331. X            complain("pushd: full stack; max of %d pushes.", NDIRS);
  332. X        DirSP++;
  333. X        setCWD(dirbuf);
  334. X    }
  335. X    prDIRS();
  336. X}
  337. X
  338. XPopd()
  339. X{
  340. X    if (DirSP == 0)
  341. X        complain("popd: directory stack is empty.");
  342. X    UpdModLine++;
  343. X    free(PWD);
  344. X    PWD = 0;
  345. X    DirSP--;
  346. X    (void) chdir(PWD);    /* If this doesn't work, we's in deep shit. */
  347. X    prDIRS();
  348. X}
  349. X
  350. Xprivate char *
  351. Xdbackup(base, offset, c)
  352. Xregister char    *base,
  353. X        *offset,
  354. X        c;
  355. X{
  356. X    while (offset > base && *--offset != c)
  357. X        ;
  358. X    return offset;
  359. X}
  360. X
  361. Xdfollow(file, into)
  362. Xchar    *file,
  363. X    *into;
  364. X{
  365. X    char    *dp,
  366. X        *sp;
  367. X
  368. X    if (*file == '/') {        /* Absolute pathname */
  369. X        strcpy(into, "/");
  370. X        file++;
  371. X    } else
  372. X        strcpy(into, PWD);
  373. X    dp = into + strlen(into);
  374. X
  375. X    sp = file;
  376. X    do {
  377. X        if (*file == 0)
  378. X            break;
  379. X        if (sp = index(file, '/'))
  380. X            *sp = 0;
  381. X        if (strcmp(file, ".") == 0)
  382. X            ;    /* So it will get to the end of the loop */
  383. X        else if (strcmp(file, "..") == 0) {
  384. X            *(dp = dbackup(into, dp, '/')) = 0;
  385. X            if (dp == into)
  386. X                strcpy(into, "/"), dp = into + 1;
  387. X        } else {
  388. X            if (into[strlen(into) - 1] != '/')
  389. X                (void) strcat(into, "/");
  390. X            (void) strcat(into, file);
  391. X            dp += strlen(file);    /* stay at the end */
  392. X        }
  393. X        file = sp + 1;
  394. X    } while (sp != 0);
  395. X}
  396. X
  397. X#endif CHDIR
  398. X
  399. Xget_hdir(user, buf)
  400. Xregister char    *user,
  401. X        *buf;
  402. X{
  403. X    char    fbuf[LBSIZE],
  404. X        pattern[100];
  405. X    register int    u_len;
  406. X    File    *fp;
  407. X
  408. X    u_len = strlen(user);
  409. X    fp = open_file("/etc/passwd", fbuf, F_READ, COMPLAIN, QUIET);
  410. X    sprintf(pattern, "%s:[^:]*:[^:]*:[^:]*:[^:]*:\\([^:]*\\):", user);
  411. X    while (f_gets(fp, genbuf, LBSIZE) != EOF)
  412. X        if ((strncmp(genbuf, user, u_len) == 0) &&
  413. X            (LookingAt(pattern, genbuf, 0))) {
  414. X            putmatch(1, buf, FILESIZE);
  415. X            close_file(fp);
  416. X            return;
  417. X        }
  418. X    f_close(fp);
  419. X    complain("[unknown user: %s]", user);
  420. X}
  421. X
  422. XPathParse(name, intobuf)
  423. Xchar    *name,
  424. X    *intobuf;
  425. X{
  426. X    char    localbuf[FILESIZE];
  427. X
  428. X    intobuf[0] = localbuf[0] = '\0';
  429. X    if (*name == '\0')
  430. X        return;
  431. X    if (*name == '~') {
  432. X        if (name[1] == '/' || name[1] == '\0') {
  433. X            strcpy(localbuf, HomeDir);
  434. X            name++;
  435. X        } else {
  436. X            char    *uendp = index(name, '/'),
  437. X                unamebuf[30];
  438. X
  439. X            if (uendp == 0)
  440. X                uendp = name + strlen(name);
  441. X            name = name + 1;
  442. X            null_ncpy(unamebuf, name, uendp - name);
  443. X            get_hdir(unamebuf, localbuf);
  444. X            name = uendp;
  445. X        }
  446. X    } else if (*name == '\\')
  447. X        name++;
  448. X    (void) strcat(localbuf, name);
  449. X#ifdef CHDIR
  450. X    dfollow(localbuf, intobuf);
  451. X#else
  452. X    strcpy(intobuf, localbuf);
  453. X#endif
  454. X}
  455. X
  456. Xfilemunge(newname)
  457. Xchar    *newname;
  458. X{
  459. X    struct stat    stbuf;
  460. X
  461. X    if (newname == 0)
  462. X        return;
  463. X    if (stat(newname, &stbuf))
  464. X        return;
  465. X    if ((stbuf.st_ino != curbuf->b_ino) &&
  466. X        ((stbuf.st_mode & S_IFMT) != S_IFCHR) &&
  467. X        (strcmp(newname, curbuf->b_fname) != 0)) {
  468. X        rbell();
  469. X        confirm("\"%s\" already exists; overwrite it? ", newname);
  470. X    }
  471. X}
  472. X
  473. XWrtReg()
  474. X{
  475. X    DoWriteReg(0);
  476. X}
  477. X
  478. XAppReg()
  479. X{
  480. X    DoWriteReg(1);
  481. X}
  482. X
  483. Xint    CreatMode = DFLT_MODE;
  484. X
  485. XDoWriteReg(app)
  486. X{
  487. X    char    fnamebuf[FILESIZE],
  488. X        *fname;
  489. X    Mark    *mp = CurMark();
  490. X    File    *fp;
  491. X
  492. X    /* Won't get here if there isn't a Mark */
  493. X    fname = ask_file((char *) 0, (char *) 0, fnamebuf);
  494. X
  495. X#ifdef BACKUPFILES
  496. X    if (!app) {
  497. X        filemunge(fname);
  498. X
  499. X        if (BkupOnWrite)
  500. X            file_backup(fname);
  501. X    }
  502. X#else
  503. X    if (!app)
  504. X        filemunge(fname);
  505. X#endif
  506. X
  507. X    fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET);
  508. X    putreg(fp, mp->m_line, mp->m_char, curline, curchar, YES);
  509. X    close_file(fp);
  510. X}
  511. X
  512. Xint    OkayBadChars = 0;
  513. X
  514. XWriteFile()
  515. X{
  516. X    char    *fname,
  517. X        fnamebuf[FILESIZE];
  518. X
  519. X    fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
  520. X    /* Don't allow bad characters when creating new files. */
  521. X    if (!OkayBadChars && strcmp(curbuf->b_fname, fnamebuf) != 0) {
  522. X        static char    *badchars = "!$^&*()~`{}\"'\\|<>? ";
  523. X        register char    *cp = fnamebuf;
  524. X        register int    c;
  525. X
  526. X        while (c = *cp++)
  527. X            if (c < ' ' || c == '\177' || index(badchars, c))
  528. X                complain("'%p': bad character in filename.", c);
  529. X    }
  530. X
  531. X    chk_mtime(curbuf, fname, "write");
  532. X    filemunge(fname);
  533. X    curbuf->b_type = B_FILE;      /* In case it wasn't before. */
  534. X    setfname(curbuf, fname);
  535. X    file_write(fname, 0);
  536. X    unmodify();
  537. X}
  538. X
  539. XFile *
  540. Xopen_file(fname, buf, how, ifbad, loudness)
  541. Xregister char    *fname;
  542. Xchar    *buf;
  543. Xregister int    how;
  544. X{
  545. X    register File    *fp;
  546. X
  547. X    io_chars = 0;
  548. X    io_lines = 0;
  549. X    tellall = loudness;
  550. X
  551. X    fp = f_open(fname, how, buf, LBSIZE);
  552. X    if (fp == NIL) {
  553. X                message(IOerr((how == F_READ) ? "open" : "create", fname));
  554. X        if (ifbad == COMPLAIN)
  555. X            complain((char *) 0);
  556. X    } else {
  557. X        int    readonly = FALSE;
  558. X
  559. X        if (access(fname, W_OK) == -1 && errno != ENOENT)
  560. X            readonly = TRUE;
  561. X                             
  562. X        if (loudness != QUIET)
  563. X            f_mess("\"%s\"%s", pr_name(fname),
  564. X                   readonly ? " [Read only]" : NullStr);
  565. X    }
  566. X    return fp;
  567. X}
  568. X
  569. X/* Check to see if the file has been modified since it was
  570. X   last written.  If so, make sure they know what they're
  571. X   doing.
  572. X
  573. X   I hate to use another stat(), but to use confirm we gotta
  574. X   do this before we open the file. */
  575. X
  576. Xchk_mtime(thisbuf, fname, how)
  577. XBuffer    *thisbuf;
  578. Xchar    *fname,
  579. X    *how;
  580. X{
  581. X    struct stat    stbuf;
  582. X    Buffer    *b;
  583. X        char    *mesg = "Shall I go ahead and %s anyway? ";
  584. X
  585. X    if ((thisbuf->b_mtime != 0) &&        /* if we care ... */
  586. X        (b = file_exists(fname)) &&        /* we already have this file */
  587. X        (b == thisbuf) &&            /* and it's the current buffer */
  588. X        (stat(fname, &stbuf) != -1) &&    /* and we can stat it */
  589. X        (stbuf.st_mtime != b->b_mtime)) {    /* and there's trouble. */
  590. X            rbell();
  591. X        redisplay();    /* Ring that bell! */
  592. X            TOstart("Warning", TRUE);
  593. X            Typeout("\"%s\" now saved on disk is not what you last", pr_name(fname));
  594. X        Typeout("visited or saved.  Probably someone else is editing");
  595. X        Typeout("your file at the same time.");
  596. X            if (how) {
  597. X            Typeout("");
  598. X            Typeout("Type \"y\" if I should %s, anyway.", how);
  599. X                f_mess(mesg, how);
  600. X        }
  601. X            TOstop();
  602. X            if (how)
  603. X                confirm(mesg, how);
  604. X    }
  605. X}
  606. X
  607. Xfile_write(fname, app)
  608. Xchar    *fname;
  609. X{
  610. X    File    *fp;
  611. X
  612. X#ifdef BACKUPFILES
  613. X    if (!app && BkupOnWrite)
  614. X        file_backup(fname);
  615. X#endif
  616. X
  617. X    fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, COMPLAIN, !QUIET);
  618. X
  619. X    if (EndWNewline) {    /* Make sure file ends with a newLine */
  620. X        Bufpos    save;
  621. X
  622. X        DOTsave(&save);
  623. X        ToLast();
  624. X        if (length(curline))    /* Not a blank Line */
  625. X            LineInsert(1);
  626. X        SetDot(&save);
  627. X    }
  628. X    putreg(fp, curbuf->b_first, 0, curbuf->b_last, length(curbuf->b_last), NO);
  629. X    set_ino(curbuf);
  630. X    close_file(fp);
  631. X}
  632. X
  633. XReadFile()
  634. X{
  635. X    char    *fname,
  636. X        fnamebuf[FILESIZE];
  637. X
  638. X    fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
  639. X    chk_mtime(curbuf, fname, "read");
  640. X
  641. X    if (IsModified(curbuf)) {
  642. X        char    *y_or_n;
  643. X        int    c;
  644. X
  645. X        for (;;) {
  646. X            rbell();
  647. X            y_or_n = ask(NullStr, "Shall I make your changes to \"%s\" permanent? ", curbuf->b_name);
  648. X            c = Upper(*y_or_n);
  649. X            if (c == 'Y' || c == 'N')
  650. X                break;
  651. X        }            
  652. X        if (c == 'Y')
  653. X            SaveFile();
  654. X    }
  655. X
  656. X    unmodify();
  657. X    initlist(curbuf);
  658. X    setfname(curbuf, fname);
  659. X    read_file(fname, 0);
  660. X}
  661. X
  662. XInsFile()
  663. X{
  664. X    char    *fname,
  665. X        fnamebuf[FILESIZE];
  666. X
  667. X    fname = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
  668. X    read_file(fname, 1);
  669. X}
  670. X
  671. X#include "temp.h"
  672. X
  673. Xint    DOLsave = 0;    /* Do Lsave flag.  If lines aren't being save
  674. X               when you think they should have been, this
  675. X               flag is probably not being set, or is being
  676. X               cleared before lsave() was called. */
  677. X
  678. Xprivate int    nleft,    /* number of good characters left in current block */
  679. X        tmpfd = -1;
  680. Xprivate disk_line    DFree = 1;
  681. X            /* pointer to end of tmp file */
  682. Xprivate char    *tfname;
  683. X
  684. Xtmpinit()
  685. X{
  686. X    char    buf[FILESIZE];
  687. X
  688. X    sprintf(buf, "%s/%s", TmpFilePath, d_tempfile);
  689. X    tfname = copystr(buf);
  690. X    tfname = mktemp(tfname);
  691. X    (void) close(creat(tfname, 0600));
  692. X    tmpfd = open(tfname, 2);
  693. X    if (tmpfd == -1)
  694. X        complain("Warning: cannot create tmp file!");
  695. X}
  696. X
  697. Xtmpclose()
  698. X{
  699. X    (void) close(tmpfd);
  700. X    tmpfd = -1;
  701. X    (void) unlink(tfname);
  702. X}
  703. X
  704. X/* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
  705. X   long. */
  706. X
  707. Xint    Jr_Len;        /* Length of Just Read Line. */
  708. Xprivate char    *getblock();
  709. X
  710. Xgetline(addr, buf)
  711. Xdisk_line    addr;
  712. Xregister char    *buf;
  713. X{
  714. X    register char    *bp,
  715. X            *lp;
  716. X
  717. X    lp = buf;
  718. X    bp = getblock(addr >> 1, READ);
  719. X    while (*lp++ = *bp++)
  720. X        ;
  721. X    Jr_Len = (lp - buf) - 1;
  722. X}
  723. X
  724. X/* Put `buf' and return the disk address */
  725. X
  726. Xdisk_line
  727. Xputline(buf)
  728. Xchar    *buf;
  729. X{
  730. X    register char    *bp,
  731. X            *lp;
  732. X    register int    nl;
  733. X    disk_line    free_ptr;
  734. X
  735. X    lp = buf;
  736. X    free_ptr = DFree;
  737. X    bp = getblock(free_ptr, WRITE);
  738. X    nl = nleft;
  739. X    free_ptr = blk_round(free_ptr);
  740. X    while (*bp = *lp++) {
  741. X        if (*bp++ == '\n') {
  742. X            *--bp = 0;
  743. X            break;
  744. X        }
  745. X        if (--nl == 0) {
  746. X            free_ptr = forward_block(free_ptr);
  747. X            DFree = free_ptr;
  748. X            bp = getblock(free_ptr, WRITE);
  749. X            lp = buf;    /* start over ... */
  750. X            nl = nleft;
  751. X        }
  752. X    }
  753. X    free_ptr = DFree;
  754. X    DFree += (((lp - buf) + CH_SIZE - 1) / CH_SIZE);
  755. X             /* (lp - buf) includes the null */
  756. X    return (free_ptr << 1);
  757. X}
  758. X
  759. X/* The theory is that critical section of code inside this procedure
  760. X   will never cause a problem to occur.  Basically, we need to ensure
  761. X   that two blocks are in memory at the same time, but I think that
  762. X   this can never screw up. */
  763. X
  764. X#define lockblock(addr)
  765. X#define unlockblock(addr)
  766. X
  767. Xdisk_line
  768. Xf_getputl(line, fp)
  769. XLine    *line;
  770. Xregister File    *fp;
  771. X{
  772. X    register char    *bp;
  773. X    register int    c,
  774. X            nl,
  775. X            max = LBSIZE;
  776. X    disk_line    free_ptr;
  777. X    char        *base;
  778. X
  779. X    free_ptr = DFree;
  780. X    base = bp = getblock(free_ptr, WRITE);
  781. X    nl = nleft;
  782. X    free_ptr = blk_round(free_ptr);
  783. X    while (--max > 0) {
  784. X        c = getc(fp);
  785. X        if (c == EOF || c == '\n')
  786. X            break;
  787. X        if (--nl == 0) {
  788. X            char    *newbp;
  789. X            int    nbytes;
  790. X
  791. X            lockblock(free_ptr);
  792. X            DFree = free_ptr = forward_block(free_ptr);
  793. X            nbytes = bp - base;
  794. X            newbp = getblock(free_ptr, WRITE);
  795. X            nl = nleft;
  796. X            byte_copy(base, newbp, nbytes);
  797. X            bp = newbp + nbytes;
  798. X            base = newbp;
  799. X            unlockblock(free_ptr);
  800. X        }
  801. X        *bp++ = c;
  802. X    }
  803. X    *bp++ = '\0';
  804. X    free_ptr = DFree;
  805. X    DFree += (((bp - base) + CH_SIZE - 1) / CH_SIZE);
  806. X    line->l_dline = (free_ptr << 1);
  807. X    if (max == 0) {
  808. X        add_mess(" [Line too long]");
  809. X        rbell();
  810. X        return EOF;
  811. X    }
  812. X    if (c == EOF) {
  813. X        if (--bp != base)
  814. X            add_mess(" [Incomplete last line]");
  815. X        return EOF;
  816. X    }
  817. X    io_lines++;
  818. X    return NIL;
  819. X}
  820. X
  821. Xtypedef struct block {
  822. X    short    b_dirty,
  823. X        b_bno;
  824. X    char    b_buf[BUFSIZ];
  825. X    struct block
  826. X        *b_LRUnext,
  827. X        *b_LRUprev,
  828. X        *b_HASHnext;
  829. X} Block;
  830. X
  831. X#define HASHSIZE    7    /* Primes work best (so I'm told) */
  832. X#define B_HASH(bno)    (bno % HASHSIZE)
  833. X
  834. Xprivate Block    b_cache[NBUF],
  835. X        *bht[HASHSIZE] = {0},        /* Block hash table */
  836. X        *f_block = 0,
  837. X        *l_block = 0;
  838. Xprivate int    max_bno = -1,
  839. X        NBlocks;
  840. X
  841. Xprivate int    (*blkio)();
  842. X
  843. Xprivate
  844. Xreal_blkio(b, iofcn)
  845. Xregister Block    *b;
  846. Xregister int    (*iofcn)();
  847. X{
  848. X    (void) lseek(tmpfd, (long) ((unsigned) b->b_bno) * BUFSIZ, 0);
  849. X    if ((*iofcn)(tmpfd, b->b_buf, BUFSIZ) != BUFSIZ)
  850. X        error("Tmp file %s error.", (iofcn == read) ? "read" : "write");
  851. X}
  852. X
  853. Xprivate
  854. Xfake_blkio(b, iofcn)
  855. Xregister Block    *b;
  856. Xregister int    (*iofcn)();
  857. X{
  858. X    tmpinit();
  859. X    blkio = real_blkio;
  860. X    real_blkio(b, iofcn);
  861. X}
  862. X
  863. Xd_cache_init()
  864. X{
  865. X    register Block    *bp,    /* Block pointer */
  866. X            **hp;    /* Hash pointer */
  867. X    register short    bno;
  868. X
  869. X    for (bp = b_cache, bno = NBUF; --bno >= 0; bp++) {
  870. X        NBlocks++;
  871. X        bp->b_dirty = 0;
  872. X        bp->b_bno = bno;
  873. X        if (l_block == 0)
  874. X            l_block = bp;
  875. X        bp->b_LRUprev = 0;
  876. X        bp->b_LRUnext = f_block;
  877. X        if (f_block != 0)
  878. X            f_block->b_LRUprev = bp;
  879. X        f_block = bp;
  880. X
  881. X        bp->b_HASHnext = *(hp = &bht[B_HASH(bno)]);
  882. X        *hp = bp;
  883. X    }
  884. X    blkio = fake_blkio;
  885. X}
  886. X
  887. XSyncTmp()
  888. X{
  889. X#ifdef MSDOS
  890. X    register int    bno = 0;
  891. X    BLock *lookup();
  892. X
  893. X    for (bno = 0; bno <= max_bno; )
  894. X        (*blkio)(lookup(bno++), write);
  895. X#else
  896. X    register Block    *b;
  897. X
  898. X    for (b = f_block; b != 0; b = b->b_LRUnext)
  899. X        if (b->b_dirty) {
  900. X            (*blkio)(b, write);
  901. X            b->b_dirty = 0;
  902. X        }
  903. X#endif
  904. X}
  905. X
  906. Xprivate Block *
  907. Xlookup(bno)
  908. Xregister short    bno;
  909. X{
  910. X    register Block    *bp;
  911. X
  912. X    for (bp = bht[B_HASH(bno)]; bp != 0; bp = bp->b_HASHnext)
  913. X        if (bp->b_bno == bno)
  914. X            break;
  915. X    return bp;
  916. X}
  917. X
  918. Xprivate
  919. XLRUunlink(b)
  920. Xregister Block    *b;
  921. X{
  922. X    if (b->b_LRUprev == 0)
  923. X        f_block = b->b_LRUnext;
  924. X    else
  925. X        b->b_LRUprev->b_LRUnext = b->b_LRUnext;
  926. X    if (b->b_LRUnext == 0)
  927. X        l_block = b->b_LRUprev;
  928. X    else
  929. X        b->b_LRUnext->b_LRUprev = b->b_LRUprev;
  930. X}
  931. X
  932. Xprivate Block *
  933. Xb_unlink(bp)
  934. Xregister Block    *bp;
  935. X{
  936. X    register Block    *hp,
  937. X            *prev = 0;
  938. X
  939. X    LRUunlink(bp);
  940. X    /* Now that we have the block, we remove it from its position
  941. X       in the hash table, so we can THEN put it somewhere else with
  942. X       it's new block assignment. */
  943. X
  944. X    for (hp = bht[B_HASH(bp->b_bno)]; hp != 0; prev = hp, hp = hp->b_HASHnext)
  945. X        if (hp == bp)
  946. X            break;
  947. X    if (hp == 0) {
  948. X        printf("\rBlock %d missing!", bp->b_bno);
  949. X        finish(0);
  950. X    }
  951. X    if (prev)
  952. X        prev->b_HASHnext = hp->b_HASHnext;
  953. X    else
  954. X        bht[B_HASH(bp->b_bno)] = hp->b_HASHnext;
  955. X
  956. X    if (bp->b_dirty) {    /* Do, now, the delayed write */
  957. X        (*blkio)(bp, write);
  958. X        bp->b_dirty = 0;
  959. X    }
  960. X
  961. X    return bp;
  962. X}
  963. X
  964. X/* Get a block which contains at least part of the line with the address
  965. X   atl.  Returns a pointer to the block and sets the global variable
  966. X   nleft (number of good characters left in the buffer). */
  967. X
  968. Xprivate char *
  969. Xgetblock(atl, iof)
  970. Xdisk_line    atl;
  971. X{
  972. X    register int    bno,
  973. X            off;
  974. X    register Block    *bp;
  975. X    static Block    *lastb = 0;
  976. X
  977. X    bno = daddr_to_bno(atl);
  978. X    off = daddr_to_off(atl);
  979. X    if (bno >= MAX_BLOCKS)
  980. X        error("Tmp file too large.  Get help!");
  981. X    nleft = BUFSIZ - off;
  982. X    if (lastb != 0 && lastb->b_bno == bno) {
  983. X        lastb->b_dirty |= iof;
  984. X        return lastb->b_buf + off;
  985. X    }
  986. X
  987. X    /* The requested block already lives in memory, so we move
  988. X       it to the end of the LRU list (making it Most Recently Used)
  989. X       and then return a pointer to it. */
  990. X    if (bp = lookup(bno)) {
  991. X        if (bp != l_block) {
  992. X            LRUunlink(bp);
  993. X            if (l_block == 0)
  994. X                f_block = l_block = bp;
  995. X            else
  996. X                l_block->b_LRUnext = bp;
  997. X            bp->b_LRUprev = l_block;
  998. X            l_block = bp;
  999. X            bp->b_LRUnext = 0;
  1000. X        }
  1001. X        if (bp->b_bno > max_bno)
  1002. X            max_bno = bp->b_bno;
  1003. X        bp->b_dirty |= iof;
  1004. X        lastb = bp;
  1005. X        return bp->b_buf + off;
  1006. X    }
  1007. X
  1008. X    /* The block we want doesn't reside in memory so we take the
  1009. X       least recently used clean block (if there is one) and use
  1010. X       it.  */
  1011. X    bp = f_block;
  1012. X    if (bp->b_dirty)    /* The best block is dirty ... */
  1013. X        SyncTmp();
  1014. X
  1015. X    bp = b_unlink(bp);
  1016. X    if (l_block == 0)
  1017. X        l_block = f_block = bp;
  1018. X    else
  1019. X        l_block->b_LRUnext = bp;    /* Place it at the end ... */
  1020. X    bp->b_LRUprev = l_block;
  1021. X    l_block = bp;
  1022. X    bp->b_LRUnext = 0;        /* so it's Most Recently Used */
  1023. X
  1024. X    bp->b_dirty = iof;
  1025. X    bp->b_bno = bno;
  1026. X    bp->b_HASHnext = bht[B_HASH(bno)];
  1027. X    bht[B_HASH(bno)] = bp;
  1028. X
  1029. X    /* Get the current contents of the block UNLESS this is a new
  1030. X       block that's never been looked at before, i.e., it's past
  1031. X       the end of the tmp file. */
  1032. X
  1033. X    if (bp->b_bno <= max_bno)
  1034. X        (*blkio)(bp, read);
  1035. X    else
  1036. X        max_bno = bno;
  1037. X
  1038. X    lastb = bp;
  1039. X    return bp->b_buf + off;
  1040. X}
  1041. X
  1042. Xchar *
  1043. Xlbptr(line)
  1044. XLine    *line;
  1045. X{
  1046. X    return getblock(line->l_dline >> 1, READ);
  1047. X}
  1048. X
  1049. X/* save the current contents of linebuf, if it has changed */
  1050. X
  1051. Xlsave()
  1052. X{
  1053. X    if (curbuf == 0 || !DOLsave)    /* Nothing modified recently */
  1054. X        return;
  1055. X
  1056. X    if (strcmp(lbptr(curline), linebuf) != 0)
  1057. X        SavLine(curline, linebuf);    /* Put linebuf on the disk. */
  1058. X    DOLsave = 0;
  1059. X}
  1060. X
  1061. X#ifdef BACKUPFILES
  1062. Xfile_backup(fname)
  1063. Xchar *fname;
  1064. X{
  1065. X    char    *s;
  1066. X    register int    i;
  1067. X    int    fd1,
  1068. X        fd2;
  1069. X    char    tmp1[BUFSIZ],
  1070. X        tmp2[BUFSIZ];
  1071. X    
  1072. X    strcpy(tmp1, fname);
  1073. X    
  1074. X    if ((s = rindex(tmp1, '/')) == NULL)
  1075. X        sprintf(tmp2, "#%s", fname);
  1076. X    else {
  1077. X        *s++ = '\0';
  1078. X        sprintf(tmp2, "%s/#%s", tmp1, s);
  1079. X    }
  1080. X
  1081. X    if ((fd1 = open(fname, 0)) < 0)
  1082. X        return;
  1083. X
  1084. X    if ((fd2 = creat(tmp2, CreatMode)) < 0) {
  1085. X        (void) close(fd1);
  1086. X        return;
  1087. X    }
  1088. X
  1089. X    while ((i = read(fd1, tmp1, sizeof(tmp1))) > 0)
  1090. X        write(fd2, tmp1, i);
  1091. X
  1092. X#ifdef BSD4_2
  1093. X    (void) fsync(fd2);
  1094. X#endif
  1095. X    (void) close(fd2);
  1096. X    (void) close(fd1);
  1097. X}
  1098. X#endif
  1099. @//E*O*F io.c//
  1100. if test 20767 -ne "`wc -c <'io.c'`"; then
  1101.     echo shar: error transmitting "'io.c'" '(should have been 20767 characters)'
  1102. fi
  1103. fi # end of overwriting check
  1104. echo shar: extracting "'iproc-pipes.c'" '(5738 characters)'
  1105. if test -f 'iproc-pipes.c' ; then 
  1106.   echo shar: will not over-write existing file "'iproc-pipes.c'"
  1107. else
  1108. sed 's/^X//' >iproc-pipes.c <<'@//E*O*F iproc-pipes.c//'
  1109. X/************************************************************************
  1110. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1111. X * provided to you without charge, and with no warranty.  You may give  *
  1112. X * away copies of JOVE, including sources, provided that this notice is *
  1113. X * included in all the files.                                           *
  1114. X ************************************************************************/
  1115. X
  1116. X#ifdef BSD4_2
  1117. X#   include <sys/wait.h>
  1118. X#else
  1119. X#   include <wait.h>
  1120. X#endif
  1121. X#include <signal.h>
  1122. X#include <sgtty.h>
  1123. X
  1124. Xtypedef struct process    Process;
  1125. X
  1126. X#define DEAD    1    /* Dead but haven't informed user yet */
  1127. X#define STOPPED    2    /* Job stopped */
  1128. X#define RUNNING    3    /* Just running */
  1129. X#define NEW    4    /* This process is brand new */
  1130. X
  1131. X/* If process is dead, flags says how. */
  1132. X#define EXITED    1
  1133. X#define KILLED    2
  1134. X
  1135. X#define isdead(p)    (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
  1136. X
  1137. X#define proc_buf(p)    (p->p_buffer->b_name)
  1138. X#define proc_cmd(p)    (p->p_name)
  1139. X#define proc_state(p)    (p->p_state)
  1140. X
  1141. Xprivate Process    *procs = 0;
  1142. X
  1143. Xint    ProcInput,
  1144. X    ProcOutput,
  1145. X    NumProcs = 0;
  1146. X
  1147. Xstatic char *
  1148. Xpstate(p)
  1149. XProcess    *p;
  1150. X{
  1151. X    switch (proc_state(p)) {
  1152. X    case NEW:
  1153. X        return "Pre-birth";
  1154. X
  1155. X    case STOPPED:
  1156. X        return "Stopped";
  1157. X
  1158. X    case RUNNING:
  1159. X        return "Running";
  1160. X
  1161. X    case DEAD:
  1162. X        if (p->p_howdied == EXITED) {
  1163. X            if (p->p_reason == 0)
  1164. X                return "Done";
  1165. X            return sprint("[Exit %d]", p->p_reason);
  1166. X        }
  1167. X        return sprint("[Killed %d]", p->p_reason);
  1168. X
  1169. X    default:
  1170. X        return "Unknown state.";
  1171. X    }
  1172. X}
  1173. X
  1174. Xstatic Process *
  1175. Xproc_pid(pid)
  1176. X{
  1177. X    register Process    *p;
  1178. X
  1179. X    for (p = procs; p != 0; p = p->p_next)
  1180. X        if (p->p_portpid == pid)
  1181. X            break;
  1182. X
  1183. X    return p;
  1184. X}
  1185. X
  1186. Xprocs_read()
  1187. X{
  1188. X    struct header {
  1189. X        int    pid;
  1190. X        int    nbytes;
  1191. X    } header;
  1192. X    int    n;
  1193. X    long    nbytes;
  1194. X    static int    here = 0;
  1195. X
  1196. X    if (here)    
  1197. X        return;
  1198. X    sighold(SIGCHLD);    /* Block any other children. */
  1199. X    here++;
  1200. X    for (;;) {
  1201. X        (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
  1202. X        if (nbytes < sizeof header)
  1203. X            break;
  1204. X        n = read(ProcInput, (char *) &header, sizeof header);
  1205. X        if (n != sizeof header)
  1206. X            finish(1);
  1207. X        read_proc(header.pid, header.nbytes);
  1208. X    }
  1209. X    redisplay();
  1210. X    here = 0;
  1211. X    sigrelse(SIGCHLD);
  1212. X}
  1213. X
  1214. Xread_proc(pid, nbytes)
  1215. Xint    pid;
  1216. Xregister int    nbytes;
  1217. X{
  1218. X    register Process    *p;
  1219. X    int    n;
  1220. X    char    ibuf[512];
  1221. X
  1222. X    if ((p = proc_pid(pid)) == 0) {
  1223. X        printf("\riproc: unknown pid (%d)", pid);
  1224. X        return;
  1225. X    }
  1226. X    if (proc_state(p) == NEW) {
  1227. X        int    rpid;
  1228. X        /* Pid of real child, not of portsrv. */
  1229. X
  1230. X        doread(ProcInput, (char *) &rpid, nbytes);
  1231. X        nbytes -= sizeof rpid;
  1232. X        p->p_pid = rpid;
  1233. X        p->p_state = RUNNING;
  1234. X    }
  1235. X
  1236. X    if (nbytes == EOF) {        /* Okay to clean up this process */
  1237. X        p->p_eof = 1;
  1238. X        NumProcs--;    /* As far as getch() in main is concerned */
  1239. X        return;
  1240. X    }
  1241. X
  1242. X    while (nbytes > 0) {
  1243. X        n = min((sizeof ibuf) - 1, nbytes);
  1244. X        doread(ProcInput, ibuf, n);
  1245. X        ibuf[n] = 0;    /* Null terminate for convenience */
  1246. X        nbytes -= n;
  1247. X        proc_rec(p, ibuf);
  1248. X    }
  1249. X}
  1250. X
  1251. XProcKill()
  1252. X{
  1253. X    proc_kill(curbuf->b_process, SIGKILL);
  1254. X}
  1255. X
  1256. XProcInt()
  1257. X{
  1258. X    proc_kill(curbuf->b_process, SIGINT);
  1259. X}
  1260. X
  1261. XProcQuit()
  1262. X{
  1263. X    proc_kill(curbuf->b_process, SIGQUIT);
  1264. X}
  1265. X
  1266. Xstatic
  1267. Xproc_close(p)
  1268. XProcess    *p;
  1269. X{
  1270. X    (void) close(p->p_toproc);
  1271. X    p->p_toproc = -1;    /* Writes will fail. */
  1272. X}
  1273. X
  1274. Xdo_rtp(mp)
  1275. Xregister Mark    *mp;
  1276. X{
  1277. X    register Process    *p = curbuf->b_process;
  1278. X    Line    *line1 = curline,
  1279. X        *line2 = mp->m_line;
  1280. X    int    char1 = curchar,
  1281. X        char2 = mp->m_char;
  1282. X    char    *gp;
  1283. X
  1284. X    if (isdead(p) || p->p_buffer != curbuf)
  1285. X        return;
  1286. X
  1287. X    (void) fixorder(&line1, &char1, &line2, &char2);
  1288. X    while (line1 != line2->l_next) {
  1289. X        gp = ltobuf(line1, genbuf) + char1;
  1290. X        if (line1 == line2)
  1291. X            gp[char2] = '\0';
  1292. X        else
  1293. X            strcat(gp, "\n");
  1294. X        (void) write(p->p_toproc, gp, strlen(gp));
  1295. X        line1 = line1->l_next;
  1296. X        char1 = 0;
  1297. X    }
  1298. X}
  1299. X
  1300. X/* VARARGS3 */
  1301. X
  1302. Xprivate
  1303. Xproc_strt(bufname, clobber, va_alist)
  1304. Xchar    *bufname;
  1305. Xva_dcl
  1306. X{
  1307. X    Window    *owind = curwind;
  1308. X    int    toproc[2],
  1309. X        pid;
  1310. X    Process    *newp;
  1311. X    Buffer    *newbuf;
  1312. X        char    *argv[32],
  1313. X            *cp,
  1314. X            foo[10],
  1315. X        cmdbuf[128];
  1316. X        int    i;
  1317. X    va_list    ap;
  1318. X
  1319. X    isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  1320. X                   or is of type B_PROCESS */
  1321. X    dopipe(toproc);
  1322. X
  1323. X    switch (pid = fork()) {
  1324. X    case -1:
  1325. X        pclose(toproc);
  1326. X        complain("[Fork failed.]");
  1327. X
  1328. X    case 0:
  1329. X            argv[0] = "portsrv";
  1330. X            argv[1] = foo;
  1331. X        sprintf(foo, "%d", ProcInput);
  1332. X        va_start(ap);
  1333. X        make_argv(&argv[2], ap);
  1334. X        va_end(ap);
  1335. X        (void) dup2(toproc[0], 0);
  1336. X        (void) dup2(ProcOutput, 1);
  1337. X        (void) dup2(ProcOutput, 2);
  1338. X        pclose(toproc);
  1339. X        execv(Portsrv, args);
  1340. X        printf("Execl failed.\n");
  1341. X        _exit(1);
  1342. X    }
  1343. X
  1344. X    sighold(SIGCHLD);
  1345. X    newp = (Process *) malloc(sizeof *newp);
  1346. X    newp->p_next = procs;
  1347. X    newp->p_state = NEW;
  1348. X    newp->p_cmd = 0;
  1349. X
  1350. X    cmdbuf[0] = '\0';
  1351. X    va_start(ap);
  1352. X    while (cp = va_arg(ap, char *))
  1353. X        sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
  1354. X    va_end(ap);
  1355. X    newp->p_name = copystr(cmdbuf);
  1356. X    procs = newp;
  1357. X    newp->p_portpid = pid;
  1358. X    newp->p_pid = -1;
  1359. X
  1360. X    newbuf = do_select((Window *) 0, bufname);
  1361. X    newbuf->b_type = B_PROCESS;
  1362. X    newp->p_buffer = newbuf;
  1363. X    newbuf->b_process = newp;    /* sorta circular, eh? */
  1364. X    pop_wind(bufname, clobber, B_PROCESS);
  1365. X    ToLast();
  1366. X    if (!bolp())
  1367. X        LineInsert(1);
  1368. X    /* Pop_wind() after everything is set up; important!
  1369. X       Bindings won't work right unless newbuf->b_process is already
  1370. X       set up BEFORE NEWBUF is first SetBuf()'d. */
  1371. X    newp->p_mark = MakeMark(curline, curchar, FLOATER);
  1372. X
  1373. X    newp->p_toproc = toproc[1];
  1374. X    newp->p_reason = 0;
  1375. X    newp->p_eof = 0;
  1376. X    NumProcs++;
  1377. X    (void) close(toproc[0]);
  1378. X    sigrelse(SIGCHLD);
  1379. X    SetWind(owind);
  1380. X}
  1381. X
  1382. Xpinit()
  1383. X{
  1384. X    int    p[2];
  1385. X
  1386. X    (void) signal(SIGCHLD, proc_child);
  1387. X    (void) pipe(p);
  1388. X    ProcInput = p[0];
  1389. X    ProcOutput = p[1];
  1390. X    (void) signal(INPUT_SIG, procs_read);
  1391. X    sighold(INPUT_SIG);    /* Released during terminal read */
  1392. X}
  1393. X
  1394. Xdoread(fd, buf, n)
  1395. Xchar    *buf;
  1396. X{
  1397. X    int    nread;
  1398. X
  1399. X    if ((nread = read(fd, buf, n)) != n)
  1400. X        complain("Cannot read %d (got %d) bytes.", n, nread);
  1401. X}
  1402. @//E*O*F iproc-pipes.c//
  1403. if test 5738 -ne "`wc -c <'iproc-pipes.c'`"; then
  1404.     echo shar: error transmitting "'iproc-pipes.c'" '(should have been 5738 characters)'
  1405. fi
  1406. fi # end of overwriting check
  1407. echo shar: extracting "'iproc-ptys.c'" '(7160 characters)'
  1408. if test -f 'iproc-ptys.c' ; then 
  1409.   echo shar: will not over-write existing file "'iproc-ptys.c'"
  1410. else
  1411. sed 's/^X//' >iproc-ptys.c <<'@//E*O*F iproc-ptys.c//'
  1412. X/************************************************************************
  1413. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1414. X * provided to you without charge, and with no warranty.  You may give  *
  1415. X * away copies of JOVE, including sources, provided that this notice is *
  1416. X * included in all the files.                                           *
  1417. X ************************************************************************/
  1418. X
  1419. X#ifdef BSD4_2
  1420. X#   include <sys/wait.h>
  1421. X#else
  1422. X#   include <wait.h>
  1423. X#endif
  1424. X#include <signal.h>
  1425. X#include <sgtty.h>
  1426. X
  1427. X#define DEAD    1    /* Dead but haven't informed user yet */
  1428. X#define STOPPED    2    /* Job stopped */
  1429. X#define RUNNING    3    /* Just running */
  1430. X#define NEW    4    /* This process is brand new */
  1431. X
  1432. X/* If process is dead, flags says how. */
  1433. X#define EXITED    1
  1434. X#define KILLED    2
  1435. X
  1436. X#define isdead(p)    (p == 0 || proc_state(p) == DEAD || p->p_fd == -1)
  1437. X
  1438. X#define proc_buf(p)    (p->p_buffer->b_name)
  1439. X#define proc_cmd(p)    (p->p_name)
  1440. X#define proc_state(p)    (p->p_state)
  1441. X
  1442. Xprivate Process    *procs = 0;
  1443. X
  1444. Xint    global_fd = 1,
  1445. X    NumProcs = 0;
  1446. X
  1447. X#ifdef BRLUNIX
  1448. X    extern struct sg_brl sg1;
  1449. X#else
  1450. X    extern struct sgttyb sg1;
  1451. X#endif
  1452. X
  1453. Xextern struct tchars tc1;
  1454. X
  1455. X#ifdef TIOCSLTC
  1456. X    extern struct ltchars ls1;
  1457. X#endif
  1458. X
  1459. Xstatic char *
  1460. Xpstate(p)
  1461. XProcess    *p;
  1462. X{
  1463. X    switch (proc_state(p)) {
  1464. X    case STOPPED:
  1465. X        return "Stopped";
  1466. X
  1467. X    case RUNNING:
  1468. X        return "Running";
  1469. X
  1470. X    case DEAD:
  1471. X        if (p->p_howdied == EXITED) {
  1472. X            if (p->p_reason == 0)
  1473. X                return "Done";
  1474. X            return sprint("exit(%d)", p->p_reason);
  1475. X        }
  1476. X        return sprint("Killed(%d)", p->p_reason);
  1477. X
  1478. X    default:
  1479. X        return "Unknown state.";
  1480. X    }
  1481. X}
  1482. X
  1483. Xstatic Process *
  1484. Xproc_pid(pid)
  1485. X{
  1486. X    register Process    *p;
  1487. X
  1488. X    for (p = procs; p != 0; p = p->p_next)
  1489. X        if (p->p_pid == pid)
  1490. X            break;
  1491. X
  1492. X    return p;
  1493. X}
  1494. X
  1495. Xread_proc(fd)
  1496. Xregister int    fd;
  1497. X{
  1498. X    register Process    *p;
  1499. X    unsigned int    n;
  1500. X    char    ibuf[1024];
  1501. X
  1502. X    for (p = procs; p != 0; p = p->p_next)
  1503. X        if (p->p_fd == fd)
  1504. X            break;
  1505. X
  1506. X    if (p == 0) {
  1507. X        printf("\riproc: unknown fd %d", fd);
  1508. X        return;
  1509. X    }
  1510. X
  1511. X    n = read(fd, ibuf, sizeof(ibuf) - 1);
  1512. X    if (n == 0) {
  1513. X        proc_close(p);
  1514. X        NumProcs--;
  1515. X        return;
  1516. X    }
  1517. X    ibuf[n] = '\0';
  1518. X    proc_rec(p, ibuf);
  1519. X    redisplay();
  1520. X}
  1521. X
  1522. XProcKill()
  1523. X{
  1524. X    register Buffer    *b;
  1525. X    Process    *buf_to_proc();
  1526. X    char    *bname;
  1527. X
  1528. X    bname = ask_buf(curbuf);
  1529. X
  1530. X    if ((b = buf_exists(bname)) == 0)
  1531. X        complain("[No such buffer]");
  1532. X    if (b->b_process == 0)
  1533. X        complain("%s not tied to a process.", bname);
  1534. X    proc_kill(b->b_process, SIGKILL);
  1535. X}
  1536. X
  1537. XProcCont()
  1538. X{
  1539. X    Process    *p;
  1540. X
  1541. X    if ((p = curbuf->b_process) == 0)
  1542. X        complain("[No process]");
  1543. X    if (p->p_state != DEAD) {
  1544. X        proc_kill(p, SIGCONT);
  1545. X        p->p_state = RUNNING;
  1546. X    }        
  1547. X}
  1548. X
  1549. XProcEof()
  1550. X{
  1551. X    send_p(tc1.t_eofc);
  1552. X}
  1553. X
  1554. XProcInt()
  1555. X{
  1556. X    send_p(tc1.t_intrc);
  1557. X}
  1558. X
  1559. XProcQuit()
  1560. X{
  1561. X    send_p(tc1.t_quitc);
  1562. X}
  1563. X
  1564. XProcStop()
  1565. X{
  1566. X    send_p(ls1.t_suspc);
  1567. X}
  1568. X
  1569. XProcDStop()
  1570. X{
  1571. X    send_p(ls1.t_dsuspc);
  1572. X}
  1573. X
  1574. Xsend_p(c)
  1575. Xchar    c;
  1576. X{
  1577. X    Process    *p;
  1578. X
  1579. X    if ((p = curbuf->b_process) == 0)
  1580. X        complain("[No process]");
  1581. X    ToLast();
  1582. X    (void) write(p->p_fd, &c, 1);
  1583. X}
  1584. X
  1585. Xstatic
  1586. Xproc_close(p)
  1587. XProcess *p;
  1588. X{
  1589. X    (void) close(p->p_fd);
  1590. X    global_fd &= ~(1 << p->p_fd);
  1591. X    p->p_eof++;
  1592. X}
  1593. X
  1594. Xdo_rtp(mp)
  1595. Xregister Mark    *mp;
  1596. X{
  1597. X    register Process    *p = curbuf->b_process;
  1598. X    Line    *line1 = curline,
  1599. X        *line2 = mp->m_line;
  1600. X    int    char1 = curchar,
  1601. X        char2 = mp->m_char;
  1602. X    char    *gp;
  1603. X
  1604. X    if (isdead(p) || p->p_buffer != curbuf)
  1605. X        return;
  1606. X
  1607. X    (void) fixorder(&line1, &char1, &line2, &char2);
  1608. X    while (line1 != line2->l_next) {
  1609. X        gp = ltobuf(line1, genbuf) + char1;
  1610. X        if (line1 == line2)
  1611. X            gp[char2] = '\0';
  1612. X        else
  1613. X            strcat(gp, "\n");
  1614. X        (void) write(p->p_fd, gp, strlen(gp));
  1615. X        line1 = line1->l_next;
  1616. X        char1 = 0;
  1617. X    }
  1618. X}
  1619. X
  1620. X/* VARARGS3 */
  1621. X
  1622. Xprivate
  1623. Xproc_strt(bufname, clobber, va_alist)
  1624. Xchar    *bufname;
  1625. Xva_dcl
  1626. X{
  1627. X    va_list    ap;
  1628. X    char    *argv[32],
  1629. X        *cp;
  1630. X    Window *owind    = curwind;
  1631. X    int    pid;
  1632. X    Process    *newp;
  1633. X    Buffer     *newbuf;
  1634. X    int    i,
  1635. X        f,
  1636. X        ttyfd;
  1637. X    long     ldisc,
  1638. X        lmode;
  1639. X    register char    *s,
  1640. X            *t;
  1641. X    extern int    errno;
  1642. X    static char    ttybuf[11],
  1643. X            ptybuf[11];
  1644. X    char    cmdbuf[128];
  1645. X#ifdef BRLUNIX
  1646. X    struct sg_brl sg;
  1647. X#else
  1648. X    struct sgttyb sg;
  1649. X#endif
  1650. X
  1651. X#ifdef TIOCGWINSZ
  1652. X    struct winsize win;
  1653. X#else
  1654. X#  ifdef BTL_BLIT
  1655. X#  include <sys/jioctl.h>
  1656. X    struct jwinsize jwin;
  1657. X#  endif
  1658. X#endif
  1659. X
  1660. X    isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  1661. X                   or is of type B_PROCESS */
  1662. X    for (s = "pqrs"; *s; s++) {
  1663. X        for (t = "0123456789abcdef"; *t; t++) {
  1664. X            sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
  1665. X            if ((ttyfd = open(ptybuf, 2)) >= 0) {
  1666. X                strcpy(ttybuf, ptybuf);
  1667. X                ttybuf[5] = 't';
  1668. X                /* make sure both ends are available */
  1669. X                if ((i = open(ttybuf, 2)) < 0)
  1670. X                    continue;
  1671. X                (void) close(i);
  1672. X                goto out;
  1673. X            }
  1674. X        }
  1675. X    }
  1676. X
  1677. Xout:    if (s == 0 && t == 0)
  1678. X        complain("[Out of ptys!]");
  1679. X
  1680. X#ifdef TIOCGETD
  1681. X    (void) ioctl(0, TIOCGETD, (struct sgttyb *) &ldisc);
  1682. X#endif
  1683. X#ifdef TIOCLGET
  1684. X    (void) ioctl(0, TIOCLGET, (struct sgttyb *) &lmode);
  1685. X#endif
  1686. X#ifdef TIOCGWINSZ
  1687. X    (void) ioctl(0, TIOCGWINSZ, (struct sgttyb *) &win);
  1688. X#else
  1689. X#  ifdef BTL_BLIT
  1690. X    (void) ioctl(0, JWINSIZE, (struct sgttyb *) &jwin);
  1691. X#  endif BTL_BLIT
  1692. X#endif
  1693. X
  1694. X    switch (pid = fork()) {
  1695. X    case -1:
  1696. X        (void) close(ttyfd);
  1697. X        complain("[Fork failed!]");
  1698. X
  1699. X    case 0:
  1700. X        for (i = 0; i < 32; i++)
  1701. X            (void) close(i);
  1702. X
  1703. X#ifdef TIOCNOTTY
  1704. X        if ((i = open("/dev/tty", 2)) >= 0) {
  1705. X            (void) ioctl(i, TIOCNOTTY, (struct sgttyb *) 0);
  1706. X            (void) close(i);
  1707. X        }
  1708. X#endif
  1709. X        i = open(ttybuf, 2);
  1710. X        for (f = 0; f <= 2; f++)
  1711. X            (void) dup2(i, f);
  1712. X
  1713. X#ifdef TIOCSETD
  1714. X        (void) ioctl(0, TIOCSETD, (struct sgttyb *) &ldisc);
  1715. X#endif
  1716. X#ifdef TIOCLSET
  1717. X        (void) ioctl(0, TIOCLSET, (struct sgttyb *) &lmode);
  1718. X#endif
  1719. X#ifdef TIOCSETC
  1720. X        (void) ioctl(0, TIOCSETC, (struct sgttyb *) &tc1);
  1721. X#endif
  1722. X#ifdef TIOCSLTC
  1723. X        (void) ioctl(0, TIOCSLTC, (struct sgttyb *) &ls1);
  1724. X#endif
  1725. X
  1726. X#ifdef TIOCGWINSZ
  1727. X#    ifdef SIGWINCH
  1728. X        (void) signal(SIGWINCH, SIG_IGN);
  1729. X#    endif
  1730. X        win.ws_row = curwind->w_height;
  1731. X        (void) ioctl(0, TIOCSWINSZ, (struct sgttyb *) &win);
  1732. X#else
  1733. X#  ifdef BTL_BLIT
  1734. X        jwin.bytesy = curwind->w_height;
  1735. X        (void) ioctl(0, JSWINSIZE, (struct sgttyb *) &jwin);
  1736. X#  endif
  1737. X#endif
  1738. X
  1739. X        sg = sg1;
  1740. X        sg.sg_flags &= ~(ECHO | CRMOD);
  1741. X        (void) stty(0, &sg);
  1742. X
  1743. X        i = getpid();
  1744. X        (void) ioctl(0, TIOCSPGRP, (struct sgttyb *) &i);
  1745. X        (void) setpgrp(0, i);
  1746. X        va_start(ap);
  1747. X        make_argv(argv, ap);
  1748. X        va_end(ap);
  1749. X        execv(argv[0], &argv[1]);
  1750. X        (void) write(1, "execve failed!\n", 15);
  1751. X        _exit(errno + 1);
  1752. X    }
  1753. X
  1754. X    sighold(SIGCHLD);
  1755. X#ifdef SIGWINCH
  1756. X    sighold(SIGWINCH);
  1757. X#endif
  1758. X    newp = (Process *) emalloc(sizeof *newp);
  1759. X
  1760. X    newp->p_fd = ttyfd;
  1761. X    newp->p_pid = pid;
  1762. X    newp->p_eof = 0;
  1763. X
  1764. X    newbuf = do_select((Window *) 0, bufname);
  1765. X    newbuf->b_type = B_PROCESS;
  1766. X    newp->p_buffer = newbuf;
  1767. X    newbuf->b_process = newp;    /* sorta circular, eh? */
  1768. X    pop_wind(bufname, clobber, B_PROCESS);
  1769. X    /* Pop_wind() after everything is set up; important!
  1770. X       Bindings won't work right unless newbuf->b_process is already
  1771. X       set up BEFORE NEWBUF is first SetBuf()'d. */
  1772. X    ToLast();
  1773. X    if (!bolp())
  1774. X        LineInsert(1);
  1775. X
  1776. X    cmdbuf[0] = '\0';
  1777. X    va_start(ap);
  1778. X    while (cp = va_arg(ap, char *))
  1779. X        sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
  1780. X    va_end(ap);
  1781. X
  1782. X    newp->p_name = copystr(cmdbuf);
  1783. X    newp->p_state = RUNNING;
  1784. X    newp->p_reason = 0;
  1785. X    newp->p_mark = MakeMark(curline, curchar, FLOATER);
  1786. X
  1787. X    newp->p_next = procs;
  1788. X    procs = newp;
  1789. X    NumProcs++;
  1790. X    global_fd |= 1 << newp->p_fd;
  1791. X    sigrelse(SIGCHLD);
  1792. X    SetWind(owind);
  1793. X}
  1794. X    
  1795. Xpinit()
  1796. X{
  1797. X    (void) signal(SIGCHLD, proc_child);
  1798. X}
  1799. @//E*O*F iproc-ptys.c//
  1800. if test 7160 -ne "`wc -c <'iproc-ptys.c'`"; then
  1801.     echo shar: error transmitting "'iproc-ptys.c'" '(should have been 7160 characters)'
  1802. fi
  1803. fi # end of overwriting check
  1804. echo shar: extracting "'iproc.c'" '(6421 characters)'
  1805. if test -f 'iproc.c' ; then 
  1806.   echo shar: will not over-write existing file "'iproc.c'"
  1807. else
  1808. sed 's/^X//' >iproc.c <<'@//E*O*F iproc.c//'
  1809. X/************************************************************************
  1810. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  1811. X * provided to you without charge, and with no warranty.  You may give  *
  1812. X * away copies of JOVE, including sources, provided that this notice is *
  1813. X * included in all the files.                                           *
  1814. X ************************************************************************/
  1815. X
  1816. X#include "jove.h"
  1817. X#include <varargs.h>
  1818. X
  1819. X#ifdef IPROCS
  1820. X
  1821. Xint    proc_child();
  1822. X
  1823. X#ifdef PIPEPROCS
  1824. X#   include "iproc-pipes.c"
  1825. X#else
  1826. X#   include "iproc-ptys.c"
  1827. X#endif
  1828. X
  1829. Xchar    proc_prompt[80] = "% ";
  1830. X
  1831. XKillProcs()
  1832. X{
  1833. X    register Process    *p;
  1834. X    register int    killem = -1;        /* -1 means undetermined */
  1835. X    register char    *yorn;
  1836. X
  1837. X    for (p = procs; p != 0; p = p->p_next)
  1838. X        if (!isdead(p)) {
  1839. X            if (killem == -1) {
  1840. X                yorn = ask("y", "Should I kill your i-processes? ");
  1841. X                killem = (Upper(*yorn) == 'Y');
  1842. X            }
  1843. X            if (killem)
  1844. X                proc_kill(p, SIGKILL);
  1845. X        }
  1846. X}
  1847. X
  1848. Xpbuftiedp(b)
  1849. Xregister Buffer    *b;
  1850. X{
  1851. X    register Process    *p = b->b_process;
  1852. X
  1853. X    if (!isdead(p))
  1854. X        complain("Process %s, attached to %b, is %s.",
  1855. X             proc_cmd(p), b, pstate(p));
  1856. X}
  1857. X
  1858. X/* Process receive: receives the characters in buf, and appends them to
  1859. X   the buffer associated with p. */
  1860. X
  1861. Xstatic
  1862. Xproc_rec(p, buf)
  1863. Xregister Process    *p;
  1864. Xchar    *buf;
  1865. X{
  1866. X    Buffer    *saveb = curbuf;
  1867. X    register Window    *w;
  1868. X    register Mark    *savepoint;
  1869. X    int    sameplace = 0,
  1870. X        do_disp = 0;
  1871. X
  1872. X    if (curwind->w_bufp == p->p_buffer)
  1873. X        w = curwind;
  1874. X    else
  1875. X        w = windbp(p->p_buffer);    /* Is this window visible? */
  1876. X    if (w != 0)
  1877. X        do_disp = (in_window(w, p->p_mark->m_line) != -1);
  1878. X    SetBuf(p->p_buffer);
  1879. X    savepoint = MakeMark(curline, curchar, FLOATER);
  1880. X    ToMark(p->p_mark);    /* Where output last stopped. */
  1881. X    if (savepoint->m_line == curline && savepoint->m_char == curchar)
  1882. X        sameplace++;
  1883. X
  1884. X    ins_str(buf, YES);
  1885. X    if (do_disp) {
  1886. X        w->w_line = curline;
  1887. X        w->w_char = curchar;
  1888. X        redisplay();
  1889. X    }
  1890. X    MarkSet(p->p_mark, curline, curchar);
  1891. X    if (!sameplace)
  1892. X        ToMark(savepoint);    /* Back to where we were. */
  1893. X    DelMark(savepoint);
  1894. X    SetBuf(saveb);
  1895. X}
  1896. X
  1897. Xproc_kill(p, sig)
  1898. Xregister Process    *p;
  1899. X{
  1900. X    if (isdead(p))
  1901. X        return;
  1902. X    if (killpg(p->p_pid, sig) == -1)
  1903. X        s_mess("Cannot kill %s!", proc_buf(p));
  1904. X}
  1905. X
  1906. X/* Deal with a process' death.  proc_rec turns on the FREEUP bit when it
  1907. X   it gets the "EOF" from portsrv.  FREEUP'd processes get unlinked from
  1908. X   the list, and the proc stucture and proc_buf(p) get free'd up, here. */
  1909. X
  1910. Xprivate
  1911. XDealWDeath()
  1912. X{
  1913. X    register Process    *p,
  1914. X                *next,
  1915. X                *prev = 0;
  1916. X    
  1917. X    for (p = procs; p != 0; p = next) {
  1918. X        next = p->p_next;
  1919. X        if (!p->p_eof) {
  1920. X            prev = p;
  1921. X            continue;
  1922. X        }
  1923. X        proc_close(p);
  1924. X        PopPBs();            /* not a process anymore */
  1925. X        p->p_buffer->b_process = 0;    /* we're killing ourself */
  1926. X        free((char *) p->p_name);
  1927. X        free((char *) p);
  1928. X        if (prev)
  1929. X            prev->p_next = next;
  1930. X        else
  1931. X            procs = next;
  1932. X    }
  1933. X}
  1934. X
  1935. XProcList()
  1936. X{
  1937. X    register Process    *p;
  1938. X    char    *fmt = "%-15s  %-15s  %-8s %s",
  1939. X        pidstr[10];
  1940. X
  1941. X    if (procs == 0) {
  1942. X        message("[No subprocesses]");
  1943. X        return;
  1944. X    }
  1945. X    TOstart("Process list", TRUE);
  1946. X
  1947. X    Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
  1948. X    Typeout(fmt, "------", "------", "--- ", "-------");
  1949. X    for (p = procs; p != 0; p = p->p_next) {
  1950. X        sprintf(pidstr, "%d", p->p_pid);
  1951. X        Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
  1952. X    }
  1953. X    DealWDeath();
  1954. X    TOstop();
  1955. X}
  1956. X
  1957. XProcNewline()
  1958. X{
  1959. X    SendData(YES);
  1960. X}
  1961. X
  1962. XProcSendData()
  1963. X{
  1964. X    SendData(NO);
  1965. X}
  1966. X
  1967. Xprivate
  1968. XSendData(newlinep)
  1969. X{
  1970. X    register Process    *p = curbuf->b_process;
  1971. X
  1972. X    if (isdead(p))
  1973. X        return;
  1974. X    if (lastp(curline)) {
  1975. X        Eol();
  1976. X        if (newlinep)
  1977. X            LineInsert(1);
  1978. X        do_rtp(p->p_mark);
  1979. X        MarkSet(p->p_mark, curline, curchar);
  1980. X    } else {
  1981. X        Bol();
  1982. X        while (LookingAt(proc_prompt, linebuf, curchar))
  1983. X            SetDot(dosearch(proc_prompt, 1, 1));
  1984. X        strcpy(genbuf, linebuf + curchar);
  1985. X        ToLast();
  1986. X        ins_str(genbuf, NO);
  1987. X    }
  1988. X}
  1989. X
  1990. XShellProc()
  1991. X{
  1992. X    char    *shbuf = "*shell*";
  1993. X    register Buffer    *b;
  1994. X
  1995. X    b = buf_exists(shbuf);
  1996. X    if (b == 0 || isdead(b->b_process))
  1997. X        proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
  1998. X    pop_wind(shbuf, NO, -1);
  1999. X}
  2000. X
  2001. XIprocess()
  2002. X{
  2003. X    extern char    ShcomBuf[100],
  2004. X            *MakeName();
  2005. X    register char    *command;
  2006. X
  2007. X    command = ask(ShcomBuf, ProcFmt);
  2008. X    null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
  2009. X    proc_strt(MakeName(command), YES, Shell, ShFlags, command, (char *) 0);
  2010. X}
  2011. X
  2012. Xproc_child()
  2013. X{
  2014. X    union wait    w;
  2015. X    register int    pid;
  2016. X
  2017. X    for (;;) {
  2018. X#ifndef VMUNIX
  2019. X        pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
  2020. X#else
  2021. X        pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
  2022. X#endif
  2023. X        if (pid <= 0)
  2024. X            break;
  2025. X        kill_off(pid, w);
  2026. X    }
  2027. X}
  2028. X
  2029. Xkill_off(pid, w)
  2030. Xregister int    pid;
  2031. Xunion wait    w;
  2032. X{
  2033. X    char    str[128];
  2034. X    register Process    *child;
  2035. X
  2036. X    if ((child = proc_pid(pid)) == 0)
  2037. X        return;
  2038. X
  2039. X    if (WIFSTOPPED(w))
  2040. X        child->p_state = STOPPED;
  2041. X    else {
  2042. X        child->p_state = DEAD;
  2043. X        if (WIFEXITED(w))
  2044. X            child->p_howdied = EXITED;
  2045. X        else if (WIFSIGNALED(w)) {
  2046. X            child->p_reason = w.w_termsig;
  2047. X            child->p_howdied = KILLED;
  2048. X        }
  2049. X        proc_close(child);
  2050. X    }
  2051. X    sprintf(str, "[Process %s: %s]\n",
  2052. X        proc_cmd(child),
  2053. X        pstate(child));
  2054. X    proc_rec(child, str);
  2055. X}
  2056. X
  2057. X/* Push/pod process bindings.  I openly acknowledge that this is a
  2058. X   kludge, but I can't be bothered making it right. */
  2059. X
  2060. Xstruct proc_bind {
  2061. X    int        pb_key;
  2062. X    data_obj    **pb_map;
  2063. X    data_obj    *pb_push;
  2064. X    data_obj    *pb_cmd;
  2065. X    struct proc_bind *pb_next;
  2066. X};
  2067. X
  2068. Xstruct proc_bind *PBinds = 0;
  2069. X
  2070. XPopPBs()
  2071. X{
  2072. X    register struct proc_bind *p;
  2073. X
  2074. X    for (p = PBinds; p != 0; p = p->pb_next)
  2075. X        p->pb_map[p->pb_key] = p->pb_push;
  2076. X}
  2077. X
  2078. XPushPBs()
  2079. X{
  2080. X    register struct proc_bind *p;
  2081. X
  2082. X    for (p = PBinds; p != 0; p = p->pb_next) {
  2083. X        p->pb_push = p->pb_map[p->pb_key];
  2084. X        p->pb_map[p->pb_key] = p->pb_cmd;
  2085. X    }
  2086. X}
  2087. X/* VARARGS0 */
  2088. X
  2089. XProcBind()
  2090. X{
  2091. X    register data_obj    *d;
  2092. X
  2093. X    if ((d = findcom(ProcFmt)) == 0)
  2094. X        return;
  2095. X    s_mess(": %f %s ", d->Name);
  2096. X    ProcB2(mainmap, EOF, d);
  2097. X}
  2098. X
  2099. XProcB2(map, lastkey, cmd)
  2100. Xdata_obj    **map,
  2101. X        *cmd;
  2102. X{
  2103. X    register struct proc_bind *p;
  2104. X    register data_obj    **nextmap;
  2105. X    int    c;
  2106. X
  2107. X    c = addgetc();
  2108. X    if (c == EOF) {
  2109. X        if (lastkey == EOF)
  2110. X            complain("[Empty key sequence]");
  2111. X        complain("[Unexpected end-of-line]");
  2112. X    } else {
  2113. X        if (nextmap = IsPrefix(map[c]))
  2114. X            ProcB2(nextmap, c, cmd);
  2115. X        else {
  2116. X            if (curbuf->b_process)
  2117. X                PopPBs();
  2118. X
  2119. X            for (p = PBinds; p != 0; p = p->pb_next)
  2120. X                if (p->pb_key == c && p->pb_map == map)
  2121. X                    break;
  2122. X            if (p == 0) {
  2123. X                p = (struct proc_bind *) emalloc(sizeof *p);
  2124. X                p->pb_next = PBinds;
  2125. X                PBinds = p;
  2126. X            }
  2127. X            p->pb_map = map;
  2128. X            p->pb_key = c;
  2129. X            p->pb_cmd = cmd;
  2130. X
  2131. X            if (curbuf->b_process)
  2132. X                PushPBs();
  2133. X        }
  2134. X    }
  2135. X}
  2136. X
  2137. X#endif IPROCS
  2138. @//E*O*F iproc.c//
  2139. if test 6421 -ne "`wc -c <'iproc.c'`"; then
  2140.     echo shar: error transmitting "'iproc.c'" '(should have been 6421 characters)'
  2141. fi
  2142. fi # end of overwriting check
  2143. echo shar: extracting "'keymaps.txt'" '(10930 characters)'
  2144. if test -f 'keymaps.txt' ; then 
  2145.   echo shar: will not over-write existing file "'keymaps.txt'"
  2146. else
  2147. sed 's/^X//' >keymaps.txt <<'@//E*O*F keymaps.txt//'
  2148. X/************************************************************************
  2149. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2150. X * provided to you without charge, and with no warranty.  You may give  *
  2151. X * away copies of JOVE, including sources, provided that this notice is *
  2152. X * included in all the files.                                           *
  2153. X ************************************************************************/
  2154. X
  2155. X/* Warning:  You probably shouldn't put ifdefs anywhere *inside* the keymaps
  2156. X   definitions.  It'll screw up the stuff in comments (at least), and maybe
  2157. X   a few other things.  Yes, it *WILL* screw up the comments ... but it's
  2158. X   not clear that you care ... */
  2159. X
  2160. X#include "jove.h"
  2161. X
  2162. Xkeymap    mainmap = {
  2163. X    "set-mark",            /* ^@ */
  2164. X    "beginning-of-line",        /* ^A */
  2165. X    "backward-character",        /* ^B */
  2166. X    "unbound",            /* ^C */
  2167. X    "delete-next-character",    /* ^D */
  2168. X    "end-of-line",            /* ^E */
  2169. X    "forward-character",        /* ^F */
  2170. X    "unbound",            /* ^G */
  2171. X    "delete-previous-character",    /* ^H */
  2172. X    "handle-tab",            /* ^I */
  2173. X    "newline-and-indent",        /* ^J */
  2174. X    "kill-to-end-of-line",        /* ^K */
  2175. X    "redraw-display",        /* ^L */
  2176. X    "newline",            /* ^M */
  2177. X    "next-line",            /* ^N */
  2178. X    "newline-and-backup",        /* ^O */
  2179. X    "previous-line",        /* ^P */
  2180. X    "quoted-insert",        /* ^Q */
  2181. X    "search-reverse",        /* ^R */
  2182. X    "search-forward",        /* ^S */
  2183. X    "transpose-characters",        /* ^T */
  2184. X    "quadruple-numeric-argument",    /* ^U */
  2185. X    "next-page",            /* ^V */
  2186. X    "kill-region",            /* ^W */
  2187. X    "prefix-2",            /* ^X */
  2188. X    "yank",                /* ^Y */
  2189. X    "scroll-up",            /* ^Z */
  2190. X    "prefix-1",            /* ^[ */
  2191. X    "search-forward",        /* ^\ */
  2192. X    "unbound",            /* ^] */
  2193. X    "quoted-insert",        /* ^^ */
  2194. X    "unbound",            /* ^_ */
  2195. X    "self-insert",            /*    */
  2196. X    "self-insert",            /* !  */
  2197. X    "self-insert",            /* "  */
  2198. X    "self-insert",            /* #  */
  2199. X    "self-insert",            /* $  */
  2200. X    "self-insert",            /* %  */
  2201. X    "self-insert",            /* &  */
  2202. X    "self-insert",            /* '  */
  2203. X    "self-insert",            /* (  */
  2204. X    "paren-flash",            /* )  */
  2205. X    "self-insert",            /* *  */
  2206. X    "self-insert",            /* +  */
  2207. X    "self-insert",            /* ,  */
  2208. X    "self-insert",            /* -  */
  2209. X    "self-insert",            /* .  */
  2210. X    "self-insert",            /* /  */
  2211. X    "self-insert",            /* 0  */
  2212. X    "self-insert",            /* 1  */
  2213. X    "self-insert",            /* 2  */
  2214. X    "self-insert",            /* 3  */
  2215. X    "self-insert",            /* 4  */
  2216. X    "self-insert",            /* 5  */
  2217. X    "self-insert",            /* 6  */
  2218. X    "self-insert",            /* 7  */
  2219. X    "self-insert",            /* 8  */
  2220. X    "self-insert",            /* 9  */
  2221. X    "self-insert",            /* :  */
  2222. X    "self-insert",            /* ;  */
  2223. X    "self-insert",            /* <  */
  2224. X    "self-insert",            /* =  */
  2225. X    "self-insert",            /* >  */
  2226. X    "self-insert",            /* ?  */
  2227. X    "self-insert",            /* @  */
  2228. X    "self-insert",            /* A  */
  2229. X    "self-insert",            /* B  */
  2230. X    "self-insert",            /* C  */
  2231. X    "self-insert",            /* D  */
  2232. X    "self-insert",            /* E  */
  2233. X    "self-insert",            /* F  */
  2234. X    "self-insert",            /* G  */
  2235. X    "self-insert",            /* H  */
  2236. X    "self-insert",            /* I  */
  2237. X    "self-insert",            /* J  */
  2238. X    "self-insert",            /* K  */
  2239. X    "self-insert",            /* L  */
  2240. X    "self-insert",            /* M  */
  2241. X    "self-insert",            /* N  */
  2242. X    "self-insert",            /* O  */
  2243. X    "self-insert",            /* P  */
  2244. X    "self-insert",            /* Q  */
  2245. X    "self-insert",            /* R  */
  2246. X    "self-insert",            /* S  */
  2247. X    "self-insert",            /* T  */
  2248. X    "self-insert",            /* U  */
  2249. X    "self-insert",            /* V  */
  2250. X    "self-insert",            /* W  */
  2251. X    "self-insert",            /* X  */
  2252. X    "self-insert",            /* Y  */
  2253. X    "self-insert",            /* Z  */
  2254. X    "self-insert",            /* [  */
  2255. X    "self-insert",            /* \  */
  2256. X    "paren-flash",            /* ]  */
  2257. X    "self-insert",            /* ^  */
  2258. X    "self-insert",            /* _  */
  2259. X    "self-insert",            /* `  */
  2260. X    "self-insert",            /* a  */
  2261. X    "self-insert",            /* b  */
  2262. X    "self-insert",            /* c  */
  2263. X    "self-insert",            /* d  */
  2264. X    "self-insert",            /* e  */
  2265. X    "self-insert",            /* f  */
  2266. X    "self-insert",            /* g  */
  2267. X    "self-insert",            /* h  */
  2268. X    "self-insert",            /* i  */
  2269. X    "self-insert",            /* j  */
  2270. X    "self-insert",            /* k  */ 
  2271. X    "self-insert",            /* l  */
  2272. X    "self-insert",            /* m  */
  2273. X    "self-insert",            /* n  */
  2274. X    "self-insert",            /* o  */
  2275. X    "self-insert",            /* p  */
  2276. X    "self-insert",            /* q  */
  2277. X    "self-insert",            /* r  */
  2278. X    "self-insert",            /* s  */
  2279. X    "self-insert",            /* t  */
  2280. X    "self-insert",            /* u  */
  2281. X    "self-insert",            /* v  */
  2282. X    "self-insert",            /* w  */
  2283. X    "self-insert",            /* x  */
  2284. X    "self-insert",            /* y  */
  2285. X    "self-insert",            /* z  */
  2286. X    "self-insert",            /* {  */
  2287. X    "self-insert",            /* |  */
  2288. X    "paren-flash",            /* }  */
  2289. X    "self-insert",            /* ~  */
  2290. X    "delete-previous-character"    /* ^? */
  2291. X};
  2292. X
  2293. Xstruct data_obj    *pref1map[0200] = {
  2294. X    "unbound",            /* ^@ */
  2295. X    "unbound",            /* ^A */
  2296. X    "backward-s-expression",    /* ^B */
  2297. X    "unbound",            /* ^C */
  2298. X    "down-list",            /* ^D */
  2299. X    "unbound",            /* ^E */
  2300. X    "forward-s-expression",        /* ^F */
  2301. X    "unbound",            /* ^G */
  2302. X    "unbound",            /* ^H */
  2303. X    "unbound",            /* ^I */
  2304. X    "unbound",            /* ^J */
  2305. X    "kill-s-expression",        /* ^K */
  2306. X    "clear-and-redraw",        /* ^L */
  2307. X    "unbound",            /* ^M */
  2308. X    "forward-list",            /* ^N */
  2309. X    "unbound",            /* ^O */
  2310. X    "backward-list",        /* ^P */
  2311. X    "unbound",            /* ^Q */
  2312. X    "unbound",            /* ^R */
  2313. X    "unbound",            /* ^S */
  2314. X    "unbound",            /* ^T */
  2315. X    "backward-up-list",        /* ^U */
  2316. X    "page-next-window",        /* ^V */
  2317. X    "unbound",            /* ^W */
  2318. X    "unbound",            /* ^X */
  2319. X    "unbound",            /* ^Y */
  2320. X    "unbound",            /* ^Z */
  2321. X    "unbound",            /* ^[ */
  2322. X    "unbound",            /* ^\ */
  2323. X    "unbound",            /* ^] */
  2324. X    "unbound",            /* ^^ */
  2325. X    "unbound",            /* ^_ */
  2326. X    "unbound",            /*    */
  2327. X    "unbound",            /* !  */
  2328. X    "unbound",            /* "  */
  2329. X    "unbound",            /* #  */
  2330. X    "unbound",            /* $  */
  2331. X    "unbound",            /* %  */
  2332. X    "unbound",            /* &  */
  2333. X    "unbound",            /* '  */
  2334. X    "unbound",            /* (  */
  2335. X    "unbound",            /* )  */
  2336. X    "unbound",            /* *  */
  2337. X    "unbound",            /* +  */
  2338. X    "beginning-of-window",        /* ,  */
  2339. X    "digit",            /* -  */
  2340. X    "end-of-window",        /* .  */
  2341. X    "unbound",            /* /  */
  2342. X    "digit",            /* 0  */
  2343. X    "digit",            /* 1  */
  2344. X    "digit",            /* 2  */
  2345. X    "digit",            /* 3  */
  2346. X    "digit",            /* 4  */
  2347. X    "digit",            /* 5  */
  2348. X    "digit",            /* 6  */
  2349. X    "digit",            /* 7  */
  2350. X    "digit",            /* 8  */
  2351. X    "digit",            /* 9  */
  2352. X    "unbound",            /* :  */
  2353. X    "unbound",            /* ;  */
  2354. X    "beginning-of-file",        /* <  */
  2355. X    "unbound",            /* =  */
  2356. X    "end-of-file",            /* >  */
  2357. X    "describe-command",        /* ?  */
  2358. X    "unbound",            /* @  */
  2359. X    "backward-sentence",        /* A  */
  2360. X    "backward-word",        /* B  */
  2361. X    "case-word-capitalize",        /* C  */
  2362. X    "kill-next-word",        /* D  */
  2363. X    "forward-sentence",        /* E  */
  2364. X    "forward-word",            /* F  */
  2365. X    "goto-line",            /* G  */
  2366. X    "unbound",            /* H  */
  2367. X    "make-macro-interactive",    /* I  */
  2368. X    "fill-paragraph",        /* J  */
  2369. X    "kill-to-end-of-sentence",    /* K  */ 
  2370. X    "case-word-lower",        /* L  */
  2371. X    "first-non-blank",        /* M  */
  2372. X    "unbound",            /* N  */
  2373. X    "unbound",            /* O  */
  2374. X    "unbound",            /* P  */
  2375. X    "query-replace-string",        /* Q  */
  2376. X    "replace-string",        /* R  */
  2377. X    "unbound",            /* S  */
  2378. X    "unbound",            /* T  */
  2379. X    "case-word-upper",        /* U  */
  2380. X    "previous-page",        /* V  */
  2381. X    "copy-region",            /* W  */
  2382. X    "execute-named-command",    /* X  */
  2383. X    "yank-pop",            /* Y  */
  2384. X    "scroll-down",            /* Z  */
  2385. X    "backward-paragraph",        /* [  */
  2386. X    "delete-white-space",        /* \  */
  2387. X    "forward-paragraph",        /* ]  */
  2388. X    "unbound",            /* ^  */
  2389. X    "unbound",            /* _  */
  2390. X    "unbound",            /* `  */
  2391. X    "backward-sentence",        /* a  */
  2392. X    "backward-word",        /* b  */
  2393. X    "case-word-capitalize",        /* c  */
  2394. X    "kill-next-word",        /* d  */
  2395. X    "forward-sentence",        /* e  */
  2396. X    "forward-word",            /* f  */
  2397. X    "goto-line",            /* g  */
  2398. X    "unbound",            /* h  */
  2399. X    "make-macro-interactive",    /* i  */
  2400. X    "fill-paragraph",        /* j  */
  2401. X    "kill-to-end-of-sentence",    /* k  */ 
  2402. X    "case-word-lower",        /* l  */
  2403. X    "first-non-blank",        /* m  */
  2404. X    "unbound",            /* n  */
  2405. X    "unbound",            /* o  */
  2406. X    "unbound",            /* p  */
  2407. X    "query-replace-string",        /* q  */
  2408. X    "replace-string",        /* r  */
  2409. X    "unbound",            /* s  */
  2410. X    "unbound",            /* t  */
  2411. X    "case-word-upper",        /* u  */
  2412. X    "previous-page",        /* v  */
  2413. X    "copy-region",            /* w  */
  2414. X    "execute-named-command",    /* x  */
  2415. X    "yank-pop",            /* y  */
  2416. X    "scroll-down",            /* z  */
  2417. X    "unbound",            /* {  */
  2418. X    "unbound",            /* |  */
  2419. X    "unbound",            /* }  */
  2420. X    "make-buffer-unmodified",    /* ~  */
  2421. X    "kill-previous-word"        /* ^? */
  2422. X};
  2423. X
  2424. Xkeymap    pref2map = {
  2425. X    "unbound",            /* ^@ */
  2426. X    "unbound",            /* ^A */
  2427. X    "list-buffers",            /* ^B */
  2428. X    "exit-jove",            /* ^C */
  2429. X    "unbound",            /* ^D */
  2430. X    "compile-it",            /* ^E */
  2431. X    "find-file",            /* ^F */
  2432. X    "unbound",            /* ^G */
  2433. X    "unbound",            /* ^H */
  2434. X    "insert-file",            /* ^I */
  2435. X    "unbound",            /* ^J */
  2436. X    "unbound",            /* ^K */
  2437. X    "unbound",            /* ^L */
  2438. X    "write-modified-files",        /* ^M */
  2439. X    "next-error",            /* ^N */
  2440. X    "delete-blank-lines",        /* ^O */
  2441. X    "previous-error",        /* ^P */
  2442. X    "unbound",            /* ^Q */
  2443. X    "visit-file",            /* ^R */
  2444. X    "save-file",            /* ^S */
  2445. X    "transpose-lines",        /* ^T */
  2446. X    "unbound",            /* ^U */
  2447. X    "visit-file",            /* ^V */
  2448. X    "write-file",            /* ^W */
  2449. X    "exchange-point-and-mark",    /* ^X */
  2450. X    "unbound",            /* ^Y */
  2451. X    "unbound",            /* ^Z */
  2452. X    "unbound",            /* ^[ */
  2453. X    "save-file",            /* ^\ */
  2454. X    "unbound",            /* ^] */
  2455. X    "unbound",            /* ^^ */
  2456. X    "unbound",            /* ^_ */
  2457. X    "unbound",            /*    */
  2458. X    "shell-command",        /* !  */
  2459. X    "unbound",            /* "  */
  2460. X    "unbound",            /* #  */
  2461. X    "unbound",            /* $  */
  2462. X    "unbound",            /* %  */
  2463. X    "unbound",            /* &  */
  2464. X    "unbound",            /* '  */
  2465. X    "start-remember",        /* (  */
  2466. X    "stop-remembering",        /* )  */
  2467. X    "unbound",            /* *  */
  2468. X    "unbound",            /* +  */
  2469. X    "unbound",            /* ,  */
  2470. X    "unbound",            /* -  */
  2471. X    "unbound",            /* .  */
  2472. X    "unbound",            /* /  */
  2473. X    "unbound",            /* 0  */
  2474. X    "delete-other-windows",        /* 1  */
  2475. X    "split-current-window",        /* 2  */
  2476. X    "unbound",            /* 3  */
  2477. X    "window-find",            /* 4  */
  2478. X    "unbound",            /* 5  */
  2479. X    "unbound",            /* 6  */
  2480. X    "unbound",            /* 7  */
  2481. X    "unbound",            /* 8  */
  2482. X    "unbound",            /* 9  */
  2483. X    "unbound",            /* :  */
  2484. X    "unbound",            /* ;  */
  2485. X    "unbound",            /* <  */
  2486. X    "unbound",            /* =  */
  2487. X    "unbound",            /* >  */
  2488. X    "describe-key",            /* ?  */
  2489. X    "unbound",            /* @  */
  2490. X    "unbound",            /* A  */
  2491. X    "select-buffer",        /* B  */
  2492. X    "unbound",            /* C  */
  2493. X    "delete-current-window",    /* D  */
  2494. X    "execute-keyboard-macro",    /* E  */
  2495. X    "unbound",            /* F  */
  2496. X    "unbound",            /* G  */
  2497. X    "unbound",            /* H  */
  2498. X    "unbound",            /* I  */
  2499. X    "unbound",            /* J  */
  2500. X    "delete-buffer",        /* K  */
  2501. X    "unbound",            /* L  */
  2502. X    "unbound",            /* M  */
  2503. X    "next-window",            /* N  */
  2504. X    "previous-window",        /* O  */
  2505. X    "previous-window",        /* P  */
  2506. X    "unbound",            /* Q  */
  2507. X    "unbound",            /* R  */
  2508. X    "save-file",        /* S  */
  2509. X    "find-tag",            /* T  */
  2510. X    "unbound",            /* U  */
  2511. X    "unbound",            /* V  */
  2512. X    "unbound",            /* W  */
  2513. X    "unbound",            /* X  */
  2514. X    "unbound",            /* Y  */
  2515. X    "unbound",            /* Z  */
  2516. X    "unbound",            /* [  */
  2517. X    "unbound",            /* \  */
  2518. X    "unbound",            /* ]  */
  2519. X    "grow-window",            /* ^  */
  2520. X    "unbound",            /* _  */
  2521. X    "unbound",            /* `  */
  2522. X    "unbound",            /* a  */
  2523. X    "select-buffer",        /* b  */
  2524. X    "unbound",            /* c  */
  2525. X    "delete-current-window",    /* d  */
  2526. X    "execute-keyboard-macro",    /* e  */
  2527. X    "unbound",            /* f  */
  2528. X    "unbound",            /* g  */
  2529. X    "unbound",            /* h  */
  2530. X    "unbound",            /* i  */
  2531. X    "unbound",            /* j  */
  2532. X    "delete-buffer",        /* k  */
  2533. X    "unbound",            /* l  */
  2534. X    "unbound",            /* m  */
  2535. X    "next-window",            /* n  */
  2536. X    "previous-window",        /* o  */
  2537. X    "previous-window",        /* p  */
  2538. X    "unbound",            /* q  */
  2539. X    "unbound",            /* r  */
  2540. X    "save-file",        /* s  */
  2541. X    "find-tag",            /* t  */
  2542. X    "unbound",            /* u  */
  2543. X    "unbound",            /* v  */
  2544. X    "unbound",            /* w  */
  2545. X    "unbound",            /* x  */
  2546. X    "unbound",            /* y  */
  2547. X    "unbound",            /* z  */
  2548. X    "unbound",            /* {  */
  2549. X    "unbound",            /* |  */
  2550. X    "unbound",            /* }  */
  2551. X    "unbound",            /* ~  */
  2552. X    "kill-to-beginning-of-sentence"    /* ^? */
  2553. X};
  2554. X
  2555. Xkeymap    miscmap = {0};
  2556. @//E*O*F keymaps.txt//
  2557. if test 10930 -ne "`wc -c <'keymaps.txt'`"; then
  2558.     echo shar: error transmitting "'keymaps.txt'" '(should have been 10930 characters)'
  2559. fi
  2560. fi # end of overwriting check
  2561. echo shar: extracting "'rec.c'" '(2901 characters)'
  2562. if test -f 'rec.c' ; then 
  2563.   echo shar: will not over-write existing file "'rec.c'"
  2564. else
  2565. sed 's/^X//' >rec.c <<'@//E*O*F rec.c//'
  2566. X/************************************************************************
  2567. X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
  2568. X * provided to you without charge, and with no warranty.  You may give  *
  2569. X * away copies of JOVE, including sources, provided that this notice is *
  2570. X * included in all the files.                                           *
  2571. X ************************************************************************/
  2572. X
  2573. X#include "jove.h"
  2574. X#include "io.h"
  2575. X#include "rec.h"
  2576. X#include <sys/file.h>
  2577. X
  2578. Xprivate int    rec_fd = 0;
  2579. Xprivate char    *recfname;
  2580. Xprivate File    *rec_out;
  2581. X
  2582. X#ifndef L_SET
  2583. X#    define L_SET 0
  2584. X#endif
  2585. X
  2586. Xprivate struct rec_head    Header;
  2587. X
  2588. Xrecinit()
  2589. X{
  2590. X    char    buf[128];
  2591. X
  2592. X    sprintf(buf, "%s/%s", TmpFilePath, p_tempfile);
  2593. X    recfname = copystr(buf);
  2594. X    recfname = mktemp(recfname);
  2595. X    rec_fd = creat(recfname, 0644);
  2596. X    if (rec_fd == -1) {
  2597. X        complain("Cannot create \"%s\"; recovery disabled.", recfname);
  2598. X        return;
  2599. X    }
  2600. X    /* Initialize the record IO. */
  2601. X    rec_out = fd_open(recfname, F_WRITE|F_LOCKED, rec_fd, iobuff, LBSIZE);
  2602. X
  2603. X    /* Initialize the record header. */
  2604. X    Header.Uid = getuid();
  2605. X    Header.Pid = getpid();
  2606. X    Header.UpdTime = 0L;
  2607. X    Header.Nbuffers = 0;
  2608. X    (void) write(rec_fd, (char *) &Header, sizeof Header);
  2609. X}
  2610. X
  2611. Xrecclose()
  2612. X{
  2613. X    if (rec_fd == -1)
  2614. X        return;
  2615. X    (void) close(rec_fd);
  2616. X    (void) unlink(recfname);
  2617. X}
  2618. X
  2619. Xstatic
  2620. Xputaddr(addr, p)
  2621. Xdisk_line    addr;
  2622. Xregister File    *p;
  2623. X{
  2624. X    register char    *cp = (char *) &addr;
  2625. X    register int    nchars = sizeof (disk_line);
  2626. X
  2627. X    while (--nchars >= 0)
  2628. X        putc(*cp++ & 0377, p);
  2629. X}
  2630. X
  2631. Xstatic
  2632. Xputn(cp, nbytes)
  2633. Xregister char    *cp;
  2634. Xregister int    nbytes;
  2635. X{
  2636. X    while (--nbytes >= 0)
  2637. X        putc(*cp++ & 0377, rec_out);
  2638. X}
  2639. X
  2640. X/* Write out the line pointers for buffer B. */
  2641. X
  2642. Xstatic
  2643. Xdmppntrs(b)
  2644. Xregister Buffer    *b;
  2645. X{
  2646. X    register Line    *lp;
  2647. X
  2648. X    for (lp = b->b_first; lp != 0; lp = lp->l_next)
  2649. X        putaddr(lp->l_dline, rec_out);
  2650. X}
  2651. X
  2652. X/* dump the buffer info and then the actual line pointers. */
  2653. X
  2654. Xstatic
  2655. Xdmp_buf(b)
  2656. Xregister Buffer    *b;
  2657. X{
  2658. X    static struct rec_entry    record;
  2659. X    register Line    *lp;
  2660. X    register int    nlines = 0;
  2661. X
  2662. X    for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
  2663. X        ;
  2664. X    strcpy(record.r_fname, b->b_fname ? b->b_fname : NullStr);
  2665. X    strcpy(record.r_bname, b->b_name);
  2666. X    record.r_nlines = nlines;
  2667. X    putn((char *) &record, sizeof record);
  2668. X    dmppntrs(b);
  2669. X}
  2670. X
  2671. X/* Goes through all the buffers and syncs them to the disk. */
  2672. X
  2673. Xint    SyncFreq = 50;
  2674. X
  2675. XSyncRec()
  2676. X{
  2677. X    register Buffer    *b;
  2678. X
  2679. X    if (rec_fd == 0)
  2680. X        recinit();    /* Init recover file. */
  2681. X    if (rec_fd == -1)
  2682. X        return;
  2683. X    lseek(rec_fd, 0L, L_SET);
  2684. X    (void) time(&Header.UpdTime);
  2685. X    Header.Nbuffers = 0;
  2686. X    for (b = world; b != 0; b = b->b_next)
  2687. X        if (b->b_type == B_SCRATCH || !IsModified(b))
  2688. X            continue;
  2689. X        else
  2690. X            Header.Nbuffers++;
  2691. X    putn((char *) &Header, sizeof Header);
  2692. X    if (Header.Nbuffers != 0) {
  2693. X        SyncTmp();
  2694. X        for (b = world; b != 0; b = b->b_next)
  2695. X            if (b->b_type == B_SCRATCH || !IsModified(b))
  2696. X                continue;
  2697. X            else
  2698. X                dmp_buf(b);
  2699. X    }
  2700. X    flush(rec_out);
  2701. X}
  2702. @//E*O*F rec.c//
  2703. if test 2901 -ne "`wc -c <'rec.c'`"; then
  2704.     echo shar: error transmitting "'rec.c'" '(should have been 2901 characters)'
  2705. fi
  2706. fi # end of overwriting check
  2707. echo shar: "End of archive 4 (of 13)."
  2708. cp /dev/null ark4isdone
  2709. DONE=true
  2710. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
  2711.     if test -f ark${I}isdone; then
  2712.         echo "You have run archive ${I}."
  2713.     else
  2714.         echo "You still need to run archive ${I}."
  2715.         DONE=false
  2716.     fi
  2717. done
  2718. case $DONE in
  2719.     true)
  2720.         echo "You have run all 13 archives."
  2721.         echo 'Now read the README and Makefile.'
  2722.         ;;
  2723. esac
  2724. ##  End of shell archive.
  2725. exit 0
  2726.